Browse Source

* fixed handling the result value of functions where the result type is
forced to something else by the compiler (internal rtl functions etc),
necessary for the objc branch
* fixed adding all used function result registers to the list of
registers that may need to be saved before a function call

git-svn-id: trunk@13695 -

Jonas Maebe 16 years ago
parent
commit
cc5aeb09de

+ 47 - 34
compiler/arm/cpupara.pas

@@ -29,7 +29,7 @@ unit cpupara;
     uses
        globtype,globals,
        aasmtai,aasmdata,
-       cpuinfo,cpubase,cgbase,
+       cpuinfo,cpubase,cgbase,cgutils,
        symconst,symbase,symtype,symdef,parabase,paramgr;
 
     type
@@ -41,10 +41,12 @@ unit cpupara;
           procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+          function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
          private
           procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
           function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
             var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+          procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
        end;
 
   implementation
@@ -52,8 +54,7 @@ unit cpupara;
     uses
        verbose,systems,
        rgobj,
-       defutil,symsym,
-       cgutils;
+       defutil,symsym;
 
 
     function tarmparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
@@ -428,40 +429,40 @@ unit cpupara;
       end;
 
 
-    function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
-      var
-        cur_stack_offset: aword;
-        curintreg, curfloatreg, curmmreg: tsuperregister;
-        retcgsize  : tcgsize;
+    procedure tarmparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
       begin
-        init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+        p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+      end;
 
-        result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
 
+    function  tarmparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
+      var
+        retcgsize  : tcgsize;
+      begin
         { Constructors return self instead of a boolean }
         if (p.proctypeoption=potype_constructor) then
           retcgsize:=OS_ADDR
         else
-          retcgsize:=def_cgsize(p.returndef);
+          retcgsize:=def_cgsize(def);
 
-        location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
-        p.funcretloc[side].size:=retcgsize;
+        location_reset(result,LOC_INVALID,OS_NO);
+        result.size:=retcgsize;
 
         { void has no location }
-        if is_void(p.returndef) then
+        if is_void(def) then
           begin
-            location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
+            location_reset(result,LOC_VOID,OS_NO);
             exit;
           end;
         { Return is passed as var parameter }
-        if ret_in_param(p.returndef,p.proccalloption) then
+        if ret_in_param(def,p.proccalloption) then
           begin
-            p.funcretloc[side].loc:=LOC_REFERENCE;
-            p.funcretloc[side].size:=retcgsize;
+            result.loc:=LOC_REFERENCE;
+            result.size:=retcgsize;
             exit;
           end;
         { Return in FPU register? }
-        if p.returndef.typ=floatdef then
+        if def.typ=floatdef then
           begin
             if (p.proccalloption in [pocall_softfloat]) or (cs_fp_emulation in current_settings.moduleswitches) then
               begin
@@ -470,17 +471,17 @@ unit cpupara;
                   OS_F64:
                     begin
                       { low }
-                      p.funcretloc[side].loc:=LOC_REGISTER;
-                      p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
-                      p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
-                      p.funcretloc[side].size:=OS_64;
+                      result.loc:=LOC_REGISTER;
+                      result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
+                      result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
+                      result.size:=OS_64;
                     end;
                   OS_32,
                   OS_F32:
                     begin
-                      p.funcretloc[side].loc:=LOC_REGISTER;
-                      p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
-                      p.funcretloc[side].size:=OS_32;
+                      result.loc:=LOC_REGISTER;
+                      result.register:=NR_FUNCTION_RETURN_REG;
+                      result.size:=OS_32;
                     end;
                   else
                     internalerror(2005082603);
@@ -488,8 +489,8 @@ unit cpupara;
               end
             else
               begin
-                p.funcretloc[side].loc:=LOC_FPUREGISTER;
-                p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+                result.loc:=LOC_FPUREGISTER;
+                result.register:=NR_FPU_RESULT_REG;
               end;
           end
           { Return in register }
@@ -498,17 +499,29 @@ unit cpupara;
             if retcgsize in [OS_64,OS_S64] then
               begin
                 { low }
-                p.funcretloc[side].loc:=LOC_REGISTER;
-                p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
-                p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
+                result.loc:=LOC_REGISTER;
+                result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
+                result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
               end
             else
               begin
-                p.funcretloc[side].loc:=LOC_REGISTER;
-                p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
+                result.loc:=LOC_REGISTER;
+                result.register:=NR_FUNCTION_RETURN_REG;
               end;
-
           end;
+      end;
+
+
+    function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
+      var
+        cur_stack_offset: aword;
+        curintreg, curfloatreg, curmmreg: tsuperregister;
+      begin
+        init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+        result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+        create_funcretloc_info(p,side);
      end;
 
 

+ 40 - 27
compiler/avr/cpupara.pas

@@ -29,7 +29,7 @@ unit cpupara;
     uses
        globtype,globals,
        aasmtai,aasmdata,
-       cpuinfo,cpubase,cgbase,
+       cpuinfo,cpubase,cgbase,cgutils,
        symconst,symbase,symtype,symdef,parabase,paramgr;
 
     type
@@ -52,8 +52,7 @@ unit cpupara;
     uses
        verbose,systems,
        rgobj,
-       defutil,symsym,
-       cgutils;
+       defutil,symsym;
 
 
     function tavrparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
@@ -396,30 +395,44 @@ unit cpupara;
 
         result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset);
 
+        create_funcretloc_info(p,side);
+     end;
+
+
+    procedure tavrparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+      begin
+        p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+      end;
+
+
+    function  tavrparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
+      var
+        retcgsize  : tcgsize;
+      begin
         { Constructors return self instead of a boolean }
         if (p.proctypeoption=potype_constructor) then
           retcgsize:=OS_ADDR
         else
-          retcgsize:=def_cgsize(p.returndef);
+          retcgsize:=def_cgsize(def);
 
-        location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
-        p.funcretloc[side].size:=retcgsize;
+        location_reset(result,LOC_INVALID,OS_NO);
+        result.size:=retcgsize;
 
         { void has no location }
-        if is_void(p.returndef) then
+        if is_void(def) then
           begin
-            location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
+            location_reset(result,LOC_VOID,OS_NO);
             exit;
           end;
         { Return is passed as var parameter }
-        if ret_in_param(p.returndef,p.proccalloption) then
+        if ret_in_param(def,p.proccalloption) then
           begin
-            p.funcretloc[side].loc:=LOC_REFERENCE;
-            p.funcretloc[side].size:=retcgsize;
+            result.loc:=LOC_REFERENCE;
+            result.size:=retcgsize;
             exit;
           end;
         { Return in FPU register? }
-        if p.returndef.typ=floatdef then
+        if def.typ=floatdef then
           begin
             if (p.proccalloption in [pocall_softfloat]) or (cs_fp_emulation in current_settings.moduleswitches) then
               begin
@@ -428,17 +441,17 @@ unit cpupara;
                   OS_F64:
                     begin
                       { low }
-                      p.funcretloc[side].loc:=LOC_REGISTER;
-                      p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
-                      p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
-                      p.funcretloc[side].size:=OS_64;
+                      result.loc:=LOC_REGISTER;
+                      result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
+                      result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
+                      result.size:=OS_64;
                     end;
                   OS_32,
                   OS_F32:
                     begin
-                      p.funcretloc[side].loc:=LOC_REGISTER;
-                      p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
-                      p.funcretloc[side].size:=OS_32;
+                      result.loc:=LOC_REGISTER;
+                      result.register:=NR_FUNCTION_RETURN_REG;
+                      result.size:=OS_32;
                     end;
                   else
                     internalerror(2005082603);
@@ -446,8 +459,8 @@ unit cpupara;
               end
             else
               begin
-                p.funcretloc[side].loc:=LOC_FPUREGISTER;
-                p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+                result.loc:=LOC_FPUREGISTER;
+                result.register:=NR_FPU_RESULT_REG;
               end;
           end
           { Return in register }
@@ -456,18 +469,18 @@ unit cpupara;
             if retcgsize in [OS_64,OS_S64] then
               begin
                 { low }
-                p.funcretloc[side].loc:=LOC_REGISTER;
-                p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
-                p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
+                result.loc:=LOC_REGISTER;
+                result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG;
+                result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG;
               end
             else
               begin
-                p.funcretloc[side].loc:=LOC_REGISTER;
-                p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG;
+                result.loc:=LOC_REGISTER;
+                result.register:=NR_FUNCTION_RETURN_REG;
               end;
 
           end;
-     end;
+      end;
 
 
     function tavrparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;

+ 30 - 24
compiler/i386/cpupara.pas

@@ -27,7 +27,7 @@ unit cpupara;
 
     uses
        globtype,
-       aasmtai,aasmdata,cpubase,cgbase,
+       aasmtai,aasmdata,cpubase,cgbase,cgutils,
        symconst,symtype,symsym,symdef,
        parabase,paramgr;
 
@@ -49,6 +49,7 @@ unit cpupara;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
           procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);override;
+          function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
        private
           procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
           procedure create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint);
@@ -61,8 +62,7 @@ unit cpupara;
     uses
        cutils,
        systems,verbose,
-       defutil,
-       cgutils;
+       defutil;
 
       const
         parasupregs : array[0..2] of tsuperregister = (RS_EAX,RS_EDX,RS_ECX);
@@ -307,6 +307,12 @@ unit cpupara;
 
 
     procedure ti386paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+      begin
+        p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+      end;
+
+
+    function  ti386paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
       var
         retcgsize  : tcgsize;
       begin
@@ -314,28 +320,28 @@ unit cpupara;
         if (p.proctypeoption=potype_constructor) then
           retcgsize:=OS_ADDR
         else
-          retcgsize:=def_cgsize(p.returndef);
+          retcgsize:=def_cgsize(def);
 
-        location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
+        location_reset(result,LOC_INVALID,OS_NO);
         { void has no location }
-        if is_void(p.returndef) then
+        if is_void(def) then
           begin
-            location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
+            location_reset(result,LOC_VOID,OS_NO);
             exit;
           end;
         { Return is passed as var parameter }
-        if ret_in_param(p.returndef,p.proccalloption) then
+        if ret_in_param(def,p.proccalloption) then
           begin
-            p.funcretloc[side].loc:=LOC_REFERENCE;
-            p.funcretloc[side].size:=retcgsize;
+            result.loc:=LOC_REFERENCE;
+            result.size:=retcgsize;
             exit;
           end;
         { Return in FPU register? }
-        if p.returndef.typ=floatdef then
+        if def.typ=floatdef then
           begin
-            p.funcretloc[side].loc:=LOC_FPUREGISTER;
-            p.funcretloc[side].register:=NR_FPU_RESULT_REG;
-            p.funcretloc[side].size:=retcgsize;
+            result.loc:=LOC_FPUREGISTER;
+            result.register:=NR_FPU_RESULT_REG;
+            result.size:=retcgsize;
           end
         else
          { Return in register }
@@ -343,26 +349,26 @@ unit cpupara;
             if retcgsize in [OS_64,OS_S64] then
              begin
                { low 32bits }
-               p.funcretloc[side].loc:=LOC_REGISTER;
-               p.funcretloc[side].size:=OS_64;
+               result.loc:=LOC_REGISTER;
+               result.size:=OS_64;
                if side=callerside then
-                 p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
+                 result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
                else
-                 p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+                 result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
                { high 32bits }
                if side=callerside then
-                 p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
+                 result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
                else
-                 p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+                 result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
              end
             else
              begin
-               p.funcretloc[side].loc:=LOC_REGISTER;
-               p.funcretloc[side].size:=retcgsize;
+               result.loc:=LOC_REGISTER;
+               result.size:=retcgsize;
                if side=callerside then
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+                 result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+                 result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
              end;
           end;
       end;

+ 68 - 30
compiler/ncgcal.pas

@@ -45,6 +45,8 @@ interface
 
        tcgcallnode = class(tcallnode)
        private
+          retloc: tlocation;
+
           procedure handle_return_value;
           procedure release_unused_return_value;
           procedure release_para_temps;
@@ -510,7 +512,6 @@ implementation
       var
         tmpcgsize,
         cgsize    : tcgsize;
-        retloc    : tlocation;
 {$ifdef cpu64bitaddr}
         ref       : treference;
 {$endif cpu64bitaddr}
@@ -529,12 +530,12 @@ implementation
           end;
 
         { Load normal (ordinal,float,pointer) result value from accumulator }
-        cgsize:=procdefinition.funcretloc[callerside].size;
-        case procdefinition.funcretloc[callerside].loc of
+        cgsize:=retloc.size;
+        case retloc.loc of
            LOC_FPUREGISTER:
              begin
                location_reset(location,LOC_FPUREGISTER,cgsize);
-               location.register:=procdefinition.funcretloc[callerside].register;
+               location.register:=retloc.register;
 {$ifdef x86}
                tcgx86(cg).inc_fpu_stack;
 {$else x86}
@@ -548,8 +549,8 @@ implementation
                  (mantis #13536).  }
                if (cnf_return_value_used in callnodeflags) then
                  begin
-                   if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
-                     cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
+                   if getsupreg(retloc.register)<first_fpu_imreg then
+                     cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.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;
@@ -567,7 +568,6 @@ implementation
                     structs with up to 16 bytes are returned in registers }
                   if cgsize in [OS_128,OS_S128] then
                     begin
-                      retloc:=procdefinition.funcretloc[callerside];
                       if retloc.loc<>LOC_REGISTER then
                         internalerror(2009042001);
                       { See #13536 comment above.  }
@@ -591,7 +591,6 @@ implementation
 {$else cpu64bitaddr}
                   if cgsize in [OS_64,OS_S64] then
                     begin
-                      retloc:=procdefinition.funcretloc[callerside];
                       if retloc.loc<>LOC_REGISTER then
                         internalerror(200409141);
                       { See #13536 comment above.  }
@@ -621,8 +620,8 @@ implementation
                       { See #13536 comment above.  }
                       if (cnf_return_value_used in callnodeflags) then
                         begin
-                          if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
-                            cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
+                          if getsupreg(retloc.register)<first_int_imreg then
+                            cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register);
 
                           { but use def_size only if it returns something valid because in
                             case of odd sized structured results in registers def_cgsize(resultdef)
@@ -633,10 +632,10 @@ implementation
                             tmpcgsize:=cgsize;
 
                           location.register:=cg.getintregister(current_asmdata.CurrAsmList,tmpcgsize);
-                          cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,tmpcgsize,procdefinition.funcretloc[callerside].register,location.register);
+                          cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,tmpcgsize,retloc.register,location.register);
                         end
                       else
-                        location:=procdefinition.funcretloc[callerside];
+                        location:=retloc;
                     end;
 {$ifdef arm}
                   if (resultdef.typ=floatdef) and (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
@@ -658,13 +657,13 @@ implementation
                if (cnf_return_value_used in callnodeflags) then
                  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);
+                   if getsupreg(retloc.register)<first_mm_imreg then
+                     cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.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);
+                   cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,retloc.register,location.register,mms_movescalar);
                  end
                else
-                 location:=procdefinition.funcretloc[callerside];
+                 location:=retloc;
              end;
 
            else
@@ -735,8 +734,8 @@ implementation
                 end;
 {$endif x86}
            end;
-            if procdefinition.funcretloc[callerside].size<>OS_NO then
-              location_free(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside]);
+            if retloc.size<>OS_NO then
+              location_free(current_asmdata.CurrAsmList,retloc);
             location_reset(location,LOC_VOID,OS_NO);
           end;
       end;
@@ -944,16 +943,49 @@ implementation
          { Include Function result registers }
          if (not is_void(resultdef)) then
           begin
-            case procdefinition.funcretloc[callerside].loc of
+            { The forced returntype may have a different size than the one
+              declared for the procdef }
+            if not assigned(typedef) then
+              retloc:=procdefinition.funcretloc[callerside]
+            else
+              retloc:=paramanager.get_funcretloc(procdefinition,callerside,typedef);
+            case retloc.loc of
               LOC_REGISTER,
               LOC_CREGISTER:
-                include(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
+                begin
+{$ifdef cpu64bitaddr}
+                  { x86-64 system v abi:
+                    structs with up to 16 bytes are returned in registers }
+                  if retloc.size in [OS_128,OS_S128] then
+                    begin
+                      include(regs_to_save_int,getsupreg(retloc.register));
+                      include(regs_to_save_int,getsupreg(retloc.registerhi));
+                    end
+                  else
+{$else cpu64bitaddr}
+                  if retloc.size in [OS_64,OS_S64] then
+                    begin
+                      include(regs_to_save_int,getsupreg(retloc.register64.reglo));
+                      include(regs_to_save_int,getsupreg(retloc.register64.reghi));
+                    end
+                  else
+{$endif not cpu64bitaddr}
+                    include(regs_to_save_int,getsupreg(retloc.register));
+                end;
               LOC_FPUREGISTER,
               LOC_CFPUREGISTER:
-                include(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
+                begin
+                  include(regs_to_save_fpu,getsupreg(retloc.register));
+{$ifdef SPARC}
+                  { SPARC uses two successive single precision fpu registers
+                    for double-precision values  }
+                  if retloc.size=OS_F64 then
+                    include(regs_to_save_fpu,succ(getsupreg(retloc.register)));
+{$endif SPARC}
+                end;
               LOC_MMREGISTER,
               LOC_CMMREGISTER:
-                include(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
+                include(regs_to_save_mm,getsupreg(retloc.register));
               LOC_REFERENCE,
               LOC_VOID:
                 ;
@@ -1145,26 +1177,32 @@ implementation
            function result }
          if (not is_void(resultdef)) then
            begin
-             case procdefinition.funcretloc[callerside].loc of
+             case retloc.loc of
                LOC_REGISTER,
                LOC_CREGISTER:
                  begin
 {$ifndef cpu64bitalu}
-                   if procdefinition.funcretloc[callerside].size in [OS_64,OS_S64] then
+                   if retloc.size in [OS_64,OS_S64] then
                      begin
-                       exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register64.reghi));
-                       exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register64.reglo));
+                       exclude(regs_to_save_int,getsupreg(retloc.register64.reghi));
+                       exclude(regs_to_save_int,getsupreg(retloc.register64.reglo));
+                     end
+{$else not cpu64bitalu}
+                   if retloc.size in [OS_128,OS_S128] then
+                     begin
+                       exclude(regs_to_save_int,getsupreg(retloc.register));
+                       exclude(regs_to_save_int,getsupreg(retloc.registerhi));
                      end
-                   else
 {$endif not cpu64bitalu}
-                     exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register));
+                   else
+                     exclude(regs_to_save_int,getsupreg(retloc.register));
                  end;
                LOC_FPUREGISTER,
                LOC_CFPUREGISTER:
-                 exclude(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register));
+                 exclude(regs_to_save_fpu,getsupreg(retloc.register));
                LOC_MMREGISTER,
                LOC_CMMREGISTER:
-                 exclude(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register));
+                 exclude(regs_to_save_mm,getsupreg(retloc.register));
                LOC_REFERENCE,
                LOC_VOID:
                  ;

+ 8 - 2
compiler/paramgr.pas

@@ -29,7 +29,7 @@ unit paramgr;
 
     uses
        cclasses,globtype,
-       cpubase,cgbase,
+       cpubase,cgbase,cgutils,
        parabase,
        aasmtai,aasmdata,
        symconst,symtype,symsym,symdef;
@@ -96,6 +96,12 @@ unit paramgr;
           }
           function  create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;virtual;abstract;
 
+          { Returns the location of the function result if p had def as
+            function result instead of its actual result. Used if the compiler
+            forces the function result to something different than the real
+            result.  }
+          function  get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;virtual;abstract;
+
           { This is used to populate the location information on all parameters
             for the routine when it is being inlined. It returns
             the size allocated on the stack
@@ -124,7 +130,7 @@ implementation
 
     uses
        systems,
-       cgobj,tgobj,cgutils,
+       cgobj,tgobj,
        defutil,verbose;
 
     { true if the location in paraloc can be reused as localloc }

+ 29 - 23
compiler/powerpc/cpupara.pas

@@ -29,7 +29,7 @@ unit cpupara;
        aasmtai,aasmdata,
        cpubase,
        symconst,symtype,symdef,symsym,
-       paramgr,parabase,cgbase;
+       paramgr,parabase,cgbase,cgutils;
 
     type
        tppcparamanager = class(tparamanager)
@@ -40,6 +40,7 @@ unit cpupara;
           procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+          function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
           procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
          private
           procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
@@ -53,7 +54,6 @@ unit cpupara;
     uses
        verbose,systems,
        defutil,
-       cgutils,
        procinfo,cpupi;
 
 
@@ -245,6 +245,12 @@ unit cpupara;
 
 
     procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+      begin
+        p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+      end;
+
+
+    function tppcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
       var
         retcgsize  : tcgsize;
       begin
@@ -252,29 +258,29 @@ unit cpupara;
         if (p.proctypeoption=potype_constructor) then
           retcgsize:=OS_ADDR
         else
-          retcgsize:=def_cgsize(p.returndef);
+          retcgsize:=def_cgsize(def);
 
-        location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
-        p.funcretloc[side].size:=retcgsize;
+        location_reset(result,LOC_INVALID,OS_NO);
+        result.size:=retcgsize;
         { void has no location }
-        if is_void(p.returndef) then
+        if is_void(def) then
           begin
-            p.funcretloc[side].loc:=LOC_VOID;
+            result.loc:=LOC_VOID;
             exit;
           end;
         { Return is passed as var parameter }
-        if ret_in_param(p.returndef,p.proccalloption) then
+        if ret_in_param(def,p.proccalloption) then
           begin
-            p.funcretloc[side].loc:=LOC_REFERENCE;
-            p.funcretloc[side].size:=retcgsize;
+            result.loc:=LOC_REFERENCE;
+            result.size:=retcgsize;
             exit;
           end;
         { Return in FPU register? }
-        if p.returndef.typ=floatdef then
+        if def.typ=floatdef then
           begin
-            p.funcretloc[side].loc:=LOC_FPUREGISTER;
-            p.funcretloc[side].register:=NR_FPU_RESULT_REG;
-            p.funcretloc[side].size:=retcgsize;
+            result.loc:=LOC_FPUREGISTER;
+            result.register:=NR_FPU_RESULT_REG;
+            result.size:=retcgsize;
           end
         else
          { Return in register }
@@ -283,26 +289,26 @@ unit cpupara;
             if retcgsize in [OS_64,OS_S64] then
              begin
                { low 32bits }
-               p.funcretloc[side].loc:=LOC_REGISTER;
+               result.loc:=LOC_REGISTER;
                if side=callerside then
-                 p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
+                 result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
                else
-                 p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+                 result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
                { high 32bits }
                if side=callerside then
-                 p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
+                 result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
                else
-                 p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+                 result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
              end
             else
 {$endif cpu64bitaddr}
              begin
-               p.funcretloc[side].loc:=LOC_REGISTER;
-               p.funcretloc[side].size:=retcgsize;
+               result.loc:=LOC_REGISTER;
+               result.size:=retcgsize;
                if side=callerside then
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+                 result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+                 result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
              end;
           end;
       end;

+ 24 - 18
compiler/powerpc64/cpupara.pas

@@ -29,7 +29,7 @@ uses
   aasmtai,aasmdata,
   cpubase,
   symconst, symtype, symdef, symsym,
-  paramgr, parabase, cgbase;
+  paramgr, parabase, cgbase, cgutils;
 
 type
   tppcparamanager = class(tparamanager)
@@ -45,6 +45,7 @@ type
     function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override;
     function create_varargs_paraloc_info(p: tabstractprocdef; varargspara:
       tvarargsparalist): longint; override;
+    function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
     procedure create_funcretloc_info(p: tabstractprocdef; side: tcallercallee);
 
   private
@@ -62,7 +63,6 @@ implementation
 uses
   verbose, systems,
   defutil,
-  cgutils,
   procinfo, cpupi;
 
 function tppcparamanager.get_volatile_registers_int(calloption:
@@ -204,6 +204,12 @@ end;
 
 procedure tppcparamanager.create_funcretloc_info(p: tabstractprocdef; side:
   tcallercallee);
+begin
+  p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+end;
+
+function tppcparamanager.get_funcretloc(p : tabstractprocdef; side:
+  tcallercallee; def: tdef): tlocation;
 var
   retcgsize: tcgsize;
 begin
@@ -211,37 +217,37 @@ begin
   if (p.proctypeoption = potype_constructor) then
     retcgsize := OS_ADDR
   else
-    retcgsize := def_cgsize(p.returndef);
+    retcgsize := def_cgsize(def);
 
-  location_reset(p.funcretloc[side], LOC_INVALID, OS_NO);
-  p.funcretloc[side].size := retcgsize;
+  location_reset(result, LOC_INVALID, OS_NO);
+  result.size := retcgsize;
   { void has no location }
-  if is_void(p.returndef) then begin
-    p.funcretloc[side].loc := LOC_VOID;
+  if is_void(def) then begin
+    result.loc := LOC_VOID;
     exit;
   end;
   { Return is passed as var parameter }
-  if ret_in_param(p.returndef, p.proccalloption) then
+  if ret_in_param(def, p.proccalloption) then
     begin
-      p.funcretloc[side].loc := LOC_REFERENCE;
-      p.funcretloc[side].size := retcgsize;
+      result.loc := LOC_REFERENCE;
+      result.size := retcgsize;
       exit;
     end;
   { Return in FPU register? }
-  if p.returndef.typ = floatdef then begin
-    p.funcretloc[side].loc := LOC_FPUREGISTER;
-    p.funcretloc[side].register := NR_FPU_RESULT_REG;
-    p.funcretloc[side].size := retcgsize;
+  if def.typ = floatdef then begin
+    result.loc := LOC_FPUREGISTER;
+    result.register := NR_FPU_RESULT_REG;
+    result.size := retcgsize;
   end else
     { Return in register }
     begin
-      p.funcretloc[side].loc := LOC_REGISTER;
-      p.funcretloc[side].size := retcgsize;
+      result.loc := LOC_REGISTER;
+      result.size := retcgsize;
       if side = callerside then
-        p.funcretloc[side].register := newreg(R_INTREGISTER,
+        result.register := newreg(R_INTREGISTER,
           RS_FUNCTION_RESULT_REG, cgsize2subreg(R_INTREGISTER, retcgsize))
       else
-        p.funcretloc[side].register := newreg(R_INTREGISTER,
+        result.register := newreg(R_INTREGISTER,
           RS_FUNCTION_RETURN_REG, cgsize2subreg(R_INTREGISTER, retcgsize));
     end;
 end;

+ 31 - 24
compiler/sparc/cpupara.pas

@@ -28,7 +28,7 @@ interface
       cclasses,
       aasmtai,aasmdata,
       cpubase,cpuinfo,
-      symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase;
+      symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase,cgutils;
 
     type
       TSparcParaManager=class(TParaManager)
@@ -41,6 +41,7 @@ interface
         procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override;
         function  create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
         function  create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override;
+        function  get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
       private
         procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
         procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist;
@@ -52,7 +53,7 @@ implementation
     uses
       cutils,verbose,systems,
       defutil,
-      cgutils,cgobj;
+      cgobj;
 
     type
       tparasupregs = array[0..5] of tsuperregister;
@@ -139,6 +140,12 @@ implementation
 
 
     procedure tsparcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+      begin
+        p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+      end;
+
+
+    function tsparcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
       var
         retcgsize  : tcgsize;
       begin
@@ -146,31 +153,31 @@ implementation
         if (p.proctypeoption=potype_constructor) then
           retcgsize:=OS_ADDR
         else
-          retcgsize:=def_cgsize(p.returndef);
+          retcgsize:=def_cgsize(def);
 
-        location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
-        p.funcretloc[side].size:=retcgsize;
+        location_reset(result,LOC_INVALID,OS_NO);
+        result.size:=retcgsize;
         { void has no location }
-        if is_void(p.returndef) then
+        if is_void(def) then
           begin
-            p.funcretloc[side].loc:=LOC_VOID;
+            result.loc:=LOC_VOID;
             exit;
           end;
         { Return is passed as var parameter }
-        if ret_in_param(p.returndef,p.proccalloption) then
+        if ret_in_param(def,p.proccalloption) then
           begin
-            p.funcretloc[side].loc:=LOC_REFERENCE;
-            p.funcretloc[side].size:=retcgsize;
+            result.loc:=LOC_REFERENCE;
+            result.size:=retcgsize;
             exit;
           end;
         { Return in FPU register? }
-        if p.returndef.typ=floatdef then
+        if def.typ=floatdef then
           begin
-            p.funcretloc[side].loc:=LOC_FPUREGISTER;
-            p.funcretloc[side].register:=NR_FPU_RESULT_REG;
+            result.loc:=LOC_FPUREGISTER;
+            result.register:=NR_FPU_RESULT_REG;
             if retcgsize=OS_F64 then
-              setsubreg(p.funcretloc[side].register,R_SUBFD);
-            p.funcretloc[side].size:=retcgsize;
+              setsubreg(result.register,R_SUBFD);
+            result.size:=retcgsize;
           end
         else
          { Return in register }
@@ -178,27 +185,27 @@ implementation
 {$ifndef cpu64bitaddr}
             if retcgsize in [OS_64,OS_S64] then
              begin
-               p.funcretloc[side].loc:=LOC_REGISTER;
+               result.loc:=LOC_REGISTER;
                { high }
                if (side=callerside) or (po_inline in p.procoptions) then
-                 p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
+                 result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
                else
-                 p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+                 result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
                { low }
                if (side=callerside) or (po_inline in p.procoptions) then
-                 p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
+                 result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
                else
-                 p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+                 result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
              end
             else
 {$endif not cpu64bitaddr}
              begin
-               p.funcretloc[side].loc:=LOC_REGISTER;
-               p.funcretloc[side].size:=retcgsize;
+               result.loc:=LOC_REGISTER;
+               result.size:=retcgsize;
                if (side=callerside) then
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+                 result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
-                 p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+                 result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
              end;
           end;
       end;

+ 39 - 33
compiler/x86_64/cpupara.pas

@@ -27,7 +27,7 @@ unit cpupara;
 
     uses
       globtype,
-      cpubase,cgbase,
+      cpubase,cgbase,cgutils,
       symconst,symtype,symsym,symdef,
       aasmtai,aasmdata,
       parabase,paramgr;
@@ -48,6 +48,7 @@ unit cpupara;
           function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
+          function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override;
        end;
 
   implementation
@@ -55,8 +56,7 @@ unit cpupara;
     uses
        cutils,verbose,
        systems,
-       defutil,
-       cgutils;
+       defutil;
 
     const
       paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9);
@@ -393,6 +393,12 @@ unit cpupara;
 
 
     procedure tx86_64paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
+      begin
+        p.funcretloc[side]:=get_funcretloc(p,side,p.returndef);
+      end;
+
+
+    function tx86_64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;
       var
         retcgsize : tcgsize;
       begin
@@ -400,38 +406,38 @@ unit cpupara;
         if (p.proctypeoption=potype_constructor) then
           retcgsize:=OS_ADDR
         else
-          retcgsize:=def_cgsize(p.returndef);
-        location_reset(p.funcretloc[side],LOC_INVALID,OS_NO);
+          retcgsize:=def_cgsize(def);
+        location_reset(result,LOC_INVALID,OS_NO);
         { void has no location }
-        if is_void(p.returndef) then
+        if is_void(def) then
           begin
-            location_reset(p.funcretloc[side],LOC_VOID,OS_NO);
+            location_reset(result,LOC_VOID,OS_NO);
             exit;
           end;
         { Return is passed as var parameter }
-        if ret_in_param(p.returndef,p.proccalloption) then
+        if ret_in_param(def,p.proccalloption) then
           begin
-            p.funcretloc[side].loc:=LOC_REFERENCE;
-            p.funcretloc[side].size:=retcgsize;
+            result.loc:=LOC_REFERENCE;
+            result.size:=retcgsize;
             exit;
           end;
         { Return in FPU register? }
-        if p.returndef.typ=floatdef then
+        if def.typ=floatdef then
           begin
-            case tfloatdef(p.returndef).floattype of
+            case tfloatdef(def).floattype of
               s32real,s64real:
                 begin
-                  p.funcretloc[side].loc:=LOC_MMREGISTER;
-                  p.funcretloc[side].register:=NR_MM_RESULT_REG;
-                  p.funcretloc[side].size:=retcgsize;
+                  result.loc:=LOC_MMREGISTER;
+                  result.register:=NR_MM_RESULT_REG;
+                  result.size:=retcgsize;
                 end;
               s64currency,
               s64comp,
               s80real:
                 begin
-                  p.funcretloc[side].loc:=LOC_FPUREGISTER;
-                  p.funcretloc[side].register:=NR_FPU_RESULT_REG;
-                  p.funcretloc[side].size:=retcgsize;
+                  result.loc:=LOC_FPUREGISTER;
+                  result.register:=NR_FPU_RESULT_REG;
+                  result.size:=retcgsize;
                 end;
               else
                 internalerror(200405034);
@@ -440,41 +446,41 @@ unit cpupara;
         else
          { Return in register }
           begin
-            p.funcretloc[side].loc:=LOC_REGISTER;
+            result.loc:=LOC_REGISTER;
             if retcgsize=OS_NO then
               begin
-                case p.returndef.size of
+                case def.size of
                   0..4:
                     begin
-                      p.funcretloc[side].size:=OS_32;
-                      p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBD);
+                      result.size:=OS_32;
+                      result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBD);
                     end;
                   5..8:
                     begin
-                      p.funcretloc[side].size:=OS_64;
-                      p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBQ);
+                      result.size:=OS_64;
+                      result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBQ);
                     end;
                   9..16:
                     begin
-                      p.funcretloc[side].size:=OS_128;
-                      p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE);
-                      p.funcretloc[side].registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE);
+                      result.size:=OS_128;
+                      result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE);
+                      result.registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE);
                     end;
                 end;
               end
             else if retcgsize in [OS_128,OS_S128] then
               begin
-                p.funcretloc[side].size:=retcgsize;
-                p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE);
-                p.funcretloc[side].registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE);                
+                result.size:=retcgsize;
+                result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE);
+                result.registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE);
               end
             else
               begin
-                p.funcretloc[side].size:=retcgsize;
+                result.size:=retcgsize;
                 if side=callerside then
-                  p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
+                  result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                 else
-                  p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
+                  result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
               end;
           end;
       end;