Browse Source

+ Fix for bug #3207 from Peter

michael 21 years ago
parent
commit
04a69ced17
1 changed files with 121 additions and 119 deletions
  1. 121 119
      compiler/ncgcal.pas

+ 121 - 119
compiler/ncgcal.pas

@@ -495,6 +495,7 @@ implementation
       begin
       begin
         resultloc:=procdefinition.funcret_paraloc[callerside];
         resultloc:=procdefinition.funcret_paraloc[callerside];
         cgsize:=resultloc.size;
         cgsize:=resultloc.size;
+
         { structured results are easy to handle....
         { structured results are easy to handle....
           needed also when result_no_used !! }
           needed also when result_no_used !! }
         if (procdefinition.proctypeoption<>potype_constructor) and
         if (procdefinition.proctypeoption<>potype_constructor) and
@@ -504,114 +505,132 @@ implementation
             if location.loc<>LOC_REFERENCE then
             if location.loc<>LOC_REFERENCE then
              internalerror(200304241);
              internalerror(200304241);
           end
           end
-        { ansi/widestrings must be registered, so we can dispose them }
-        else if resulttype.def.needs_inittable then
+        else
+          { ansi/widestrings must be registered, so we can dispose them }
+          if resulttype.def.needs_inittable then
+            begin
+              { the FUNCTION_RESULT_REG is already allocated }
+              if not assigned(funcretnode) then
+                begin
+                  location_reset(location,LOC_REFERENCE,OS_ADDR);
+                  location.reference:=refcountedtemp;
+                  { a_load_reg_ref may allocate registers! }
+                  cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,location.reference);
+                  cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
+                end
+              else
+                begin
+                  cg.ungetregister(exprasmlist,resultloc.register);
+                  hregister := cg.getaddressregister(exprasmlist);
+                  cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,resultloc.register,hregister);
+                  { in case of a regular funcretnode with ret_in_param, the }
+                  { original funcretnode isn't touched -> make sure it's    }
+                  { the same here (not sure if it's necessary)              }
+                  tempnode := funcretnode.getcopy;
+                  tempnode.pass_2;
+                  location := tempnode.location;
+                  tempnode.free;
+                  cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference,false);
+                  cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
+                  cg.ungetregister(exprasmlist,hregister);
+               end;
+
+              { When the result is not used we need to finalize the result and
+                can release the temp }
+              if not(cnf_return_value_used in callnodeflags) then
+                begin
+                  cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
+                  tg.ungetiftemp(exprasmlist,location.reference)
+                end;
+            end
+        else
+          { normal (ordinal,float,pointer) result value }
           begin
           begin
-            { the FUNCTION_RESULT_REG is already allocated }
-            if not assigned(funcretnode) then
-              begin
-                location_reset(location,LOC_REFERENCE,OS_ADDR);
-                location.reference:=refcountedtemp;
-                { a_load_reg_ref may allocate registers! }
-                cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,location.reference);
-                cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
-              end
-            else
+            { we have only to handle the result if it is used }
+            if (cnf_return_value_used in callnodeflags) then
               begin
               begin
-                cg.ungetregister(exprasmlist,resultloc.register);
-                hregister := cg.getaddressregister(exprasmlist);
-                cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,resultloc.register,hregister);
-                { in case of a regular funcretnode with ret_in_param, the }
-                { original funcretnode isn't touched -> make sure it's    }
-                { the same here (not sure if it's necessary)              }
-                tempnode := funcretnode.getcopy;
-                tempnode.pass_2;
-                location := tempnode.location;
-                tempnode.free;
-                cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference,false);
-                cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
-                cg.ungetregister(exprasmlist,hregister);
-             end;
-          end
-        { we have only to handle the result if it is used }
-        else if (cnf_return_value_used in callnodeflags) then
-          begin
-            location.loc:=resultloc.loc;
-            case resultloc.loc of
-               LOC_FPUREGISTER:
-                 begin
-                   location_reset(location,LOC_FPUREGISTER,cgsize);
-                   location.register:=procdefinition.funcret_paraloc[callerside].register;
+                location.loc:=resultloc.loc;
+                case resultloc.loc of
+                   LOC_FPUREGISTER:
+                     begin
+                       location_reset(location,LOC_FPUREGISTER,cgsize);
+                       location.register:=procdefinition.funcret_paraloc[callerside].register;
 {$ifdef x86}
 {$ifdef x86}
-                   tcgx86(cg).inc_fpu_stack;
+                       tcgx86(cg).inc_fpu_stack;
 {$else x86}
 {$else x86}
-                   cg.ungetregister(exprasmlist,location.register);
-                   hregister:=cg.getfpuregister(exprasmlist,location.size);
-                   cg.a_loadfpu_reg_reg(exprasmlist,location.size,location.register,hregister);
-                   location.register:=hregister;
+                       cg.ungetregister(exprasmlist,location.register);
+                       hregister:=cg.getfpuregister(exprasmlist,location.size);
+                       cg.a_loadfpu_reg_reg(exprasmlist,location.size,location.register,hregister);
+                       location.register:=hregister;
 {$endif x86}
 {$endif x86}
-                 end;
+                     end;
 
 
-               LOC_REGISTER:
-                 begin
-                   if cgsize<>OS_NO then
-                    begin
-                      location_reset(location,LOC_REGISTER,cgsize);
+                   LOC_REGISTER:
+                     begin
+                       if cgsize<>OS_NO then
+                        begin
+                          location_reset(location,LOC_REGISTER,cgsize);
 {$ifndef cpu64bit}
 {$ifndef cpu64bit}
-                      if cgsize in [OS_64,OS_S64] then
-                       begin
-                         { Move the function result to free registers, preferably the
-                           FUNCTION_RESULT_REG/FUNCTION_RESULTHIGH_REG, so no move is necessary.}
-                         { the FUNCTION_RESULT_LOW_REG/FUNCTION_RESULT_HIGH_REG
-                           are already allocated }
-                         cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_LOW_REG);
-                         location.registerlow:=cg.getintregister(exprasmlist,OS_32);
-                         cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_LOW_REG,location.registerlow);
-                         cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_HIGH_REG);
-                         location.registerhigh:=cg.getintregister(exprasmlist,OS_32);
-                         cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_HIGH_REG,location.registerhigh);
-                       end
-                      else
+                          if cgsize in [OS_64,OS_S64] then
+                           begin
+                             { Move the function result to free registers, preferably the
+                               FUNCTION_RESULT_REG/FUNCTION_RESULTHIGH_REG, so no move is necessary.}
+                             { the FUNCTION_RESULT_LOW_REG/FUNCTION_RESULT_HIGH_REG
+                               are already allocated }
+                             cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_LOW_REG);
+                             location.registerlow:=cg.getintregister(exprasmlist,OS_32);
+                             cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_LOW_REG,location.registerlow);
+                             cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_HIGH_REG);
+                             location.registerhigh:=cg.getintregister(exprasmlist,OS_32);
+                             cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_HIGH_REG,location.registerhigh);
+                           end
+                          else
 {$endif cpu64bit}
 {$endif cpu64bit}
-                       begin
-                         { Move the function result to a free register, preferably the
-                           FUNCTION_RESULT_REG, so no move is necessary.}
-                         { the FUNCTION_RESULT_REG is already allocated }
-                         cg.ungetregister(exprasmlist,resultloc.register);
-                         { change register size after the unget because the
-                           getregister was done for the full register
-
-                           def_cgsize(resulttype.def) is used here because
-                           it could be a constructor call }
-                         location.register:=cg.getintregister(exprasmlist,def_cgsize(resulttype.def));
-                         cg.a_load_reg_reg(exprasmlist,cgsize,def_cgsize(resulttype.def),resultloc.register,location.register);
-                       end;
-                    end
-                   else
-                    begin
-                      if resulttype.def.size>0 then
-                        internalerror(200305131);
-                    end;
-                 end;
+                           begin
+                             { Move the function result to a free register, preferably the
+                               FUNCTION_RESULT_REG, so no move is necessary.}
+                             { the FUNCTION_RESULT_REG is already allocated }
+                             cg.ungetregister(exprasmlist,resultloc.register);
+                             { change register size after the unget because the
+                               getregister was done for the full register
+
+                               def_cgsize(resulttype.def) is used here because
+                               it could be a constructor call }
+                             location.register:=cg.getintregister(exprasmlist,def_cgsize(resulttype.def));
+                             cg.a_load_reg_reg(exprasmlist,cgsize,def_cgsize(resulttype.def),resultloc.register,location.register);
+                           end;
+                        end
+                       else
+                        begin
+                          if resulttype.def.size>0 then
+                            internalerror(200305131);
+                        end;
+                     end;
 
 
-               LOC_MMREGISTER:
-                 begin
-                   location_reset(location,LOC_MMREGISTER,cgsize);
-                   cg.ungetregister(exprasmlist,resultloc.register);
-                   location.register:=cg.getmmregister(exprasmlist,cgsize);
-                   cg.a_loadmm_reg_reg(exprasmlist,cgsize,cgsize,resultloc.register,location.register,mms_movescalar);
-                 end;
+                   LOC_MMREGISTER:
+                     begin
+                       location_reset(location,LOC_MMREGISTER,cgsize);
+                       cg.ungetregister(exprasmlist,resultloc.register);
+                       location.register:=cg.getmmregister(exprasmlist,cgsize);
+                       cg.a_loadmm_reg_reg(exprasmlist,cgsize,cgsize,resultloc.register,location.register,mms_movescalar);
+                     end;
 
 
-               else
-                 internalerror(200405023);
-             end;
-          end
-        else
-          begin
-            if cgsize<>OS_NO then
-              paramanager.freeparaloc(exprasmlist,resultloc);
-            location_reset(location,LOC_VOID,OS_NO);
-          end;
+                   else
+                     internalerror(200405023);
+                end;
+              end
+            else
+              begin
+{$ifdef x86}
+                { release FPU stack }
+                if resultloc.loc=LOC_FPUREGISTER then
+                  emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
+{$endif x86}
+                if cgsize<>OS_NO then
+                  paramanager.freeparaloc(exprasmlist,resultloc);
+                location_reset(location,LOC_VOID,OS_NO);
+              end;
+           end;
       end;
       end;
 
 
 
 
@@ -1024,26 +1043,6 @@ implementation
 
 
          { release temps of paras }
          { release temps of paras }
          release_para_temps;
          release_para_temps;
-
-         { if return value is not used }
-         if (not(cnf_return_value_used in callnodeflags)) and (not is_void(resulttype.def)) then
-           begin
-              if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
-                begin
-                   { data which must be finalized ? }
-                   if (resulttype.def.needs_inittable) then
-                      cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
-                   { release unused temp }
-                   tg.ungetiftemp(exprasmlist,location.reference)
-                end
-              else if location.loc=LOC_FPUREGISTER then
-                begin
-{$ifdef x86}
-                  { release FPU stack }
-                  emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
-{$endif x86}
-                end;
-           end;
       end;
       end;
 
 
 
 
@@ -1264,7 +1263,10 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.172  2004-07-11 19:01:13  peter
+  Revision 1.173  2004-07-12 10:47:42  michael
+  + Fix for bug 3207 from Peter
+
+  Revision 1.172  2004/07/11 19:01:13  peter
     * comps are passed in int registers
     * comps are passed in int registers
 
 
   Revision 1.171  2004/07/09 23:41:04  jonas
   Revision 1.171  2004/07/09 23:41:04  jonas