Selaa lähdekoodia

* generate code for procvar first before pushing parameters. Made
the already existing code for powerpc available for all platforms

peter 22 vuotta sitten
vanhempi
commit
5e40220d67
1 muutettua tiedostoa jossa 101 lisäystä ja 141 poistoa
  1. 101 141
      compiler/ncgcal.pas

+ 101 - 141
compiler/ncgcal.pas

@@ -440,126 +440,93 @@ implementation
         { we have only to handle the result if it is used }
          if (nf_return_value_used in flags) then
           begin
-            case resulttype.def.deftype of
-              enumdef,
-              orddef :
-                begin
-                  cgsize:=def_cgsize(resulttype.def);
+            if (resulttype.def.deftype=floatdef) then
+              begin
+                location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
+{$ifdef cpufpemu}
+                if cs_fp_emulation in aktmoduleswitches then
+                  location.register.enum := accumulator
+               else
+{$endif cpufpemu}
+                location.register.enum:=FPU_RESULT_REG;
+{$ifdef x86}
+                inc(trgcpu(rg).fpuvaroffset);
+{$endif x86}
+              end
+            else
+              begin
+                cgsize:=def_cgsize(resulttype.def);
 
-                  { an object constructor is a function with pointer result }
-                  if (inlined or (right=nil)) and
-                     (procdefinition.proctypeoption=potype_constructor) then
-                    cgsize:=OS_ADDR;
+                { an object constructor is a function with pointer result }
+                if (inlined or (right=nil)) and
+                   (procdefinition.proctypeoption=potype_constructor) then
+                  cgsize:=OS_ADDR;
 
-                  if cgsize<>OS_NO then
-                   begin
-                     location_reset(location,LOC_REGISTER,cgsize);
+                if cgsize<>OS_NO then
+                 begin
+                   location_reset(location,LOC_REGISTER,cgsize);
 {$ifndef cpu64bit}
-                     if cgsize in [OS_64,OS_S64] then
-                      begin
-                        {Move the function result to free registers, preferably the
-                         accumulator/accumulatorhigh, so no move is necessary.}
-                        r.enum:=R_INTREGISTER;
-                        r.number:=NR_ACCUMULATOR;
-                        hregister.enum:=R_INTREGISTER;
-                        hregister.number:=NR_ACCUMULATORHIGH;
+                   if cgsize in [OS_64,OS_S64] then
+                    begin
+                      {Move the function result to free registers, preferably the
+                       accumulator/accumulatorhigh, so no move is necessary.}
+                      r.enum:=R_INTREGISTER;
+                      r.number:=NR_ACCUMULATOR;
+                      hregister.enum:=R_INTREGISTER;
+                      hregister.number:=NR_ACCUMULATORHIGH;
 {$ifdef newra}
-                        rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR);
-                        rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH);
-                        rg.ungetregisterint(exprasmlist,r);
-                        rg.ungetregisterint(exprasmlist,hregister);
+                      rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR);
+                      rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH);
+                      rg.ungetregisterint(exprasmlist,r);
+                      rg.ungetregisterint(exprasmlist,hregister);
+                      location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
+                      location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
+{$else newra}
+                      cg.a_reg_alloc(exprasmlist,r);
+                      cg.a_reg_alloc(exprasmlist,hregister);
+                      if RS_ACCUMULATOR in rg.unusedregsint then
+                        location.registerlow:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
+                      else
                         location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
+                      if RS_ACCUMULATORHIGH in rg.unusedregsint then
+                        location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH)
+                      else
                         location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
-{$else newra}
-                        cg.a_reg_alloc(exprasmlist,r);
-                        cg.a_reg_alloc(exprasmlist,hregister);
-                        if RS_ACCUMULATOR in rg.unusedregsint then
-                          location.registerlow:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
-                        else
-                          location.registerlow:=rg.getregisterint(exprasmlist,OS_INT);
-                        if RS_ACCUMULATORHIGH in rg.unusedregsint then
-                          location.registerhigh:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATORHIGH)
-                        else
-                          location.registerhigh:=rg.getregisterint(exprasmlist,OS_INT);
-{$endif newra}
-                        cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
-                            location.register64);
-                      end
-                     else
-{$endif cpu64bit}
-                      begin
-                        {Move the function result to a free register, preferably the
-                         accumulator, so no move is necessary.}
-                        nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize);
-                        r.enum:=R_INTREGISTER;
-                        r.number:=nr;
-{$ifdef newra}
-                        rg.getexplicitregisterint(exprasmlist,nr);
-                        rg.ungetregisterint(exprasmlist,r);
-                        location.register:=rg.getregisterint(exprasmlist,cgsize);
-{$else newra}
-                        cg.a_reg_alloc(exprasmlist,r);
-                        if RS_ACCUMULATOR in rg.unusedregsint then
-                          location.register:=rg.getexplicitregisterint(exprasmlist,nr)
-                        else
-                          location.register:=rg.getregisterint(exprasmlist,cgsize);
 {$endif newra}
-                        cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,r,location.register);
-                      end;
-                   end;
-                end;
-              floatdef :
-                begin
-                  location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
-{$ifdef cpufpemu}
-                  if cs_fp_emulation in aktmoduleswitches then
-                    location.register.enum := accumulator
-                 else
-{$endif cpufpemu}
-                  location.register.enum:=FPU_RESULT_REG;
-{$ifdef x86}
-                  inc(trgcpu(rg).fpuvaroffset);
-{$endif x86}
-                end;
-{$ifdef TEST_WIN32_RECORDS}
-              recorddef :
-                begin
-                  if (target_info.system=system_i386_win32) then
-                   begin
-                     location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
-                     tg.GetTemp(exprasmlist,resulttype.size,tt_normal,location);
-{$ifndef cpu64bit}
-                     if cgsize in [OS_64,OS_S64] then
-                       cg64.a_load64_reg_loc(exprasmlist,joinreg64(accumulator,accumulatorhigh),location)
-                     else
+                      cg64.a_load64_reg_reg(exprasmlist,joinreg64(r,hregister),
+                          location.register64);
+                    end
+                   else
 {$endif cpu64bit}
-                       cg.a_load_reg_loc(exprasmlist,accumulator,location);
-                   end
-                  else
-                   internalerror(200211141);
-                end;
-{$endif TEST_WIN32_RECORDS}
-              else
-                begin
-                  location_reset(location,LOC_REGISTER,OS_INT);
-                  r.enum:=R_INTREGISTER;
-                  r.number:=NR_ACCUMULATOR;
+                    begin
+                      {Move the function result to a free register, preferably the
+                       accumulator, so no move is necessary.}
+                      nr:=RS_ACCUMULATOR shl 8 or cgsize2subreg(cgsize);
+                      r.enum:=R_INTREGISTER;
+                      r.number:=nr;
 {$ifdef newra}
-                  rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR);
-                  rg.ungetregisterint(exprasmlist,r);
-                  location.register:=rg.getregisterint(exprasmlist,OS_INT);
+                      rg.getexplicitregisterint(exprasmlist,nr);
+                      rg.ungetregisterint(exprasmlist,r);
+                      location.register:=rg.getregisterint(exprasmlist,cgsize);
 {$else newra}
-                  if RS_ACCUMULATOR in rg.unusedregsint then
-                    location.register:=rg.getexplicitregisterint(exprasmlist,NR_ACCUMULATOR)
-                  else
-                    location.register:=rg.getregisterint(exprasmlist,OS_INT);
+                      cg.a_reg_alloc(exprasmlist,r);
+                      if RS_ACCUMULATOR in rg.unusedregsint then
+                        location.register:=rg.getexplicitregisterint(exprasmlist,nr)
+                      else
+                        location.register:=rg.getregisterint(exprasmlist,cgsize);
 {$endif newra}
-                  cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,r,location.register);
-                end;
-            end;
-         end
+                      cg.a_load_reg_reg(exprasmlist,cgsize,cgsize,r,location.register);
+                    end;
+                 end
+                else
+                 begin
+                   if resulttype.def.size>0 then
+                     internalerror(200305131);
+                 end;
+              end;
+          end
         else
-         location_reset(location,LOC_VOID,OS_NO);
+          location_reset(location,LOC_VOID,OS_NO);
       end;
 
 
@@ -579,13 +546,13 @@ implementation
          pp : tcallparanode;
          inlined : boolean;
          inlinecode : tprocinlinenode;
+         pushedregs : tmaybesave;
          store_parast_fixup,
          para_alignment,
          para_offset : longint;
          pop_size : longint;
          returnref,
          pararef : treference;
-         vmtreg,
          accreg : tregister;
          oldaktcallnode : tcallnode;
       begin
@@ -701,7 +668,6 @@ implementation
          oldaktcallnode:=aktcallnode;
          aktcallnode:=self;
 
-{$ifdef powerpc}
          { process procvar. Done here already, because otherwise it may }
          { destroy registers containing a parameter for the actual      }
          { function call (e.g. if it's a function, its result will      }
@@ -718,25 +684,31 @@ implementation
                 begin
                    secondpass(methodpointer);
                    location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
-                   vmtreg:=methodpointer.location.register;
 
                    { virtual methods require an index }
                    if tprocdef(procdefinition).extnumber=-1 then
                      internalerror(200304021);
                    { VMT should already be loaded in a register }
-                   if vmtreg.number=NR_NO then
+                   if methodpointer.location.register.number=NR_NO then
                      internalerror(200304022);
 
                    { test validity of VMT }
                    if not(is_interface(tprocdef(procdefinition)._class)) and
                       not(is_cppclass(tprocdef(procdefinition)._class)) then
-                     cg.g_maybe_testvmt(exprasmlist,vmtreg,tprocdef(procdefinition)._class);
+                     cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
                 end;
            end;
-{$endif powerpc}
 
          if assigned(left) then
            begin
+            {$ifndef newra}
+              if assigned(right) then
+                maybe_save(exprasmlist,left.registers32,right.location,pushedregs)
+              else
+                if assigned(methodpointer) then
+                  maybe_save(exprasmlist,left.registers32,methodpointer.location,pushedregs);
+
+            {$endif}
               { be found elsewhere }
               if inlined then
                 para_offset:=tprocdef(procdefinition).parast.address_fixup+
@@ -752,6 +724,13 @@ implementation
                 tcallparanode(left).secondcallparan(
                   (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
                   para_alignment,para_offset);
+            {$ifndef newra}
+              if assigned(right) then
+                maybe_restore(exprasmlist,right.location,pushedregs)
+              else
+                if assigned(methodpointer) then
+                  maybe_restore(exprasmlist,methodpointer.location,pushedregs);
+            {$endif newra}
            end;
          aktcallnode:=oldaktcallnode;
 
@@ -783,31 +762,13 @@ implementation
               if (po_virtualmethod in procdefinition.procoptions) and
                  assigned(methodpointer) then
                 begin
-{$ifndef powerpc}
-                   secondpass(methodpointer);
-                   location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
-                   vmtreg:=methodpointer.location.register;
-
-                   { virtual methods require an index }
-                   if tprocdef(procdefinition).extnumber=-1 then
-                     internalerror(200304021);
-                   { VMT should already be loaded in a register }
-                   if vmtreg.number=NR_NO then
-                     internalerror(200304022);
-
-                   { test validity of VMT }
-                   if not(is_interface(tprocdef(procdefinition)._class)) and
-                      not(is_cppclass(tprocdef(procdefinition)._class)) then
-                     cg.g_maybe_testvmt(exprasmlist,vmtreg,tprocdef(procdefinition)._class);
-{$endif powerpc}
-
                    { call method }
-                   reference_reset_base(href,vmtreg,
+                   reference_reset_base(href,methodpointer.location.register,
                       tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
                    cg.a_call_ref(exprasmlist,href);
 
                    { release self }
-                   rg.ungetaddressregister(exprasmlist,vmtreg);
+                   rg.ungetaddressregister(exprasmlist,methodpointer.location.register);
                 end
               else
                 begin
@@ -833,10 +794,6 @@ implementation
          else
            { now procedure variable case }
            begin
-{$ifndef powerpc}
-              secondpass(right);
-{$endif not powerpc}
-
               { Calling interrupt from the same code requires some
                 extra code }
               if (po_interrupt in procdefinition.procoptions) then
@@ -877,8 +834,7 @@ implementation
             pop_size:=pushedparasize;
             { for Cdecl functions we don't need to pop the funcret when it
               was pushed by para }
-            if (procdefinition.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
-               paramanager.ret_in_param(procdefinition.rettype.def,procdefinition.proccalloption) then
+            if paramanager.ret_in_param(procdefinition.rettype.def,procdefinition.proccalloption) then
               dec(pop_size,POINTER_SIZE);
           end;
 
@@ -1184,7 +1140,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.61  2003-05-12 18:17:55  jonas
+  Revision 1.62  2003-05-13 15:18:18  peter
+    * generate code for procvar first before pushing parameters. Made
+      the already existing code for powerpc available for all platforms
+
+  Revision 1.61  2003/05/12 18:17:55  jonas
     * moved fpc_check_object call earlier for the ppc, so it can't destroy
       already-loaded parameter registers