Просмотр исходного кода

* issameref() to test if two references are the same (then emit no opcodes)
+ ret_in_reg to replace ret_in_acc
(fix some register allocation bugs at the same time)
+ save_std_register now has an extra parameter which is the
usedinproc registers

carl 23 лет назад
Родитель
Сommit
745efb2c47

+ 60 - 26
compiler/cgobj.pas

@@ -98,18 +98,11 @@ unit cgobj;
              was previously allocated using @link(get_scratch_reg).
           }
           procedure free_scratch_reg(list : taasmoutput;r : tregister);
-
-          { passing parameters, per default the parameter is pushed }
-          { nr gives the number of the parameter (enumerated from   }
-          { left to right), this allows to move the parameter to    }
-          { register, if the cpu supports register calling          }
-          { conventions                                             }
-
           {# Pass a parameter, which is located in a register, to a routine.
 
              This routine should push/send the parameter to the routine, as
-             required by the specific processor ABI. This must be overriden for
-             each CPU target.
+             required by the specific processor ABI and routine modifiers. 
+             This must be overriden for each CPU target.
 
              @param(size size of the operand in the register)
              @param(r register source of the operand)
@@ -118,7 +111,9 @@ unit cgobj;
           procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const locpara : tparalocation);virtual;
           {# Pass a parameter, which is a constant, to a routine.
 
-             A generic version is provided.
+             A generic version is provided. This routine should
+             be overriden for optimization purposes if the cpu
+             permits directly sending this type of parameter.
 
              @param(size size of the operand in constant)
              @param(a value of constant to send)
@@ -127,7 +122,9 @@ unit cgobj;
           procedure a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);virtual;
           {# Pass the value of a parameter, which is located in memory, to a routine.
 
-             A generic version is provided.
+             A generic version is provided. This routine should
+             be overriden for optimization purposes if the cpu
+             permits directly sending this type of parameter.
 
              @param(size size of the operand in constant)
              @param(r Memory reference of value to send)
@@ -148,17 +145,16 @@ unit cgobj;
              will calculate the address of the reference, and pass this
              calculated address as a parameter.
 
-             A generic version is provided.
+             A generic version is provided. This routine should
+             be overriden for optimization purposes if the cpu
+             permits directly sending this type of parameter.
 
              @param(r reference to get address from)
              @param(nr parameter number (starting from one) of routine (from left to right))
           }
           procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);virtual;
 
-          {**********************************}
-          { these methods must be overriden: }
-
-          { Remarks:
+          (* Remarks:
             * If a method specifies a size you have only to take care
               of that number of bits, i.e. load_const_reg with OP_8 must
               only load the lower 8 bit of the specified register
@@ -173,7 +169,7 @@ unit cgobj;
             * the procedures without fpu/mm are only for integer usage
             * normally the first location is the source and the
               second the destination
-          }
+          *)
 
           {# Emits instruction to call the method specified by symbol name.
              This routine must be overriden for each new target cpu.
@@ -266,7 +262,8 @@ unit cgobj;
              save should be done either to a temp (pointed to by href).
              or on the stack (pushing the value on the stack).
 
-             The size of the value to save is OS_S32.
+             The size of the value to save is OS_S32. The default version
+             saves the exception reason to a temp. memory area.
           }
          procedure g_exception_reason_save(list : taasmoutput; const href : treference);virtual;
          {#
@@ -275,7 +272,8 @@ unit cgobj;
              save should be done either to a temp (pointed to by href).
              or on the stack (pushing the value on the stack).
 
-             The size of the value to save is OS_S32
+             The size of the value to save is OS_S32. The default version
+             saves the exception reason to a temp. memory area.
           }
          procedure g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aword);virtual;
          {#
@@ -284,7 +282,8 @@ unit cgobj;
              should either be in the temp. area (pointed to by href , href should
              *NOT* be freed) or on the stack (the value should be popped).
 
-             The size of the value to restore is OS_S32.
+             The size of the value to save is OS_S32. The default version
+             saves the exception reason to a temp. memory area.
           }
          procedure g_exception_reason_load(list : taasmoutput; const href : treference);virtual;
 
@@ -344,9 +343,6 @@ unit cgobj;
           {# Generates overflow checking code for a node }
           procedure g_overflowcheck(list: taasmoutput; const p: tnode); virtual; abstract;
 
-          {**********************************}
-          {    entry/exit code helpers       }
-
           procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;elesize:integer); virtual; abstract;
           {# Emits instructions which should be emitted when entering
              a routine declared as @var(interrupt). The default
@@ -386,10 +382,31 @@ unit cgobj;
           procedure g_call_constructor_helper(list : taasmoutput);virtual;
           procedure g_call_destructor_helper(list : taasmoutput);virtual;
           procedure g_call_fail_helper(list : taasmoutput);virtual;
-          procedure g_save_standard_registers(list : taasmoutput);virtual;abstract;
-          procedure g_restore_standard_registers(list : taasmoutput);virtual;abstract;
+          {# This routine is called when generating the code for the entry point
+             of a routine. It should save all registers which are not used in this
+             routine, and which should be declared as saved in the std_saved_registers
+             set. 
+             
+             This routine is mainly used when linking to code which is generated
+             by ABI-compliant compilers (like GCC), to make sure that the reserved
+             registers of that ABI are not clobbered.
+             
+             @param(usedinproc Registers which are used in the code of this routine)
+          }             
+          procedure g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);virtual;abstract;
+          {# This routine is called when generating the code for the exit point
+             of a routine. It should restore all registers which were previously 
+             saved in @var(g_save_standard_registers).
+
+             @param(usedinproc Registers which are used in the code of this routine)
+          }             
+          procedure g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);virtual;abstract;
           procedure g_save_all_registers(list : taasmoutput);virtual;abstract;
           procedure g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);virtual;abstract;
+          {# This routine verifies if two references are the same, and
+             if so, returns TRUE, otherwise returns false.
+          }
+          function issameref(const sref, dref : treference):boolean; 
        end;
 
     {# @abstract(Abstract code generator for 64 Bit operations)
@@ -621,6 +638,9 @@ unit cgobj;
 {$endif i386}
 
       begin
+        { verify if we have the same reference }
+        if issameref(sref,dref) then
+          exit;
 {$ifdef i386}
         { the following is done with defines to avoid a speed penalty,  }
         { since all this is only necessary for the 80x86 (because EDI   }
@@ -1508,6 +1528,13 @@ unit cgobj;
      end;
 
 
+    function tcg.issameref(const sref, dref : treference):boolean; 
+      begin
+        if CompareByte(sref,dref,sizeof(treference))=0 then
+          issameref := true
+        else
+          issameref := false;
+      end;
 
 
 
@@ -1533,7 +1560,14 @@ finalization
 end.
 {
   $Log$
-  Revision 1.49  2002-08-15 08:13:54  carl
+  Revision 1.50  2002-08-16 14:24:57  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.49  2002/08/15 08:13:54  carl
     - a_load_sym_ofs_reg removed
     * loadvmt now calls loadaddr_ref_reg instead
 

+ 32 - 14
compiler/m68k/cgcpu.pas

@@ -69,12 +69,9 @@ unit cgcpu;
           procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
           { restores the previous frame pointer at procedure exit }
           procedure g_restore_frame_pointer(list : taasmoutput);override;
-          { This routine should update the stack pointer so that parasize are freed
-            from the stack. It should also emit the return instruction
-          }  
           procedure g_return_from_proc(list : taasmoutput;parasize : aword);override;
-          procedure g_save_standard_registers(list : taasmoutput);override;
-          procedure g_restore_standard_registers(list : taasmoutput);override;
+          procedure g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
+          procedure g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
           procedure g_save_all_registers(list : taasmoutput);override;
           procedure g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);override;
      protected
@@ -113,7 +110,7 @@ Implementation
     uses
        globtype,globals,verbose,systems,cutils,
        symdef,symsym,defbase,paramgr,
-       rgobj,tgobj,rgcpu;
+       rgobj,tgobj,rgcpu,cg64f32;
 
          
     const     
@@ -365,11 +362,11 @@ Implementation
               end;
           OP_DIV :
               Begin
-{$warning To complete DIV opcode}              
+                 internalerror(20020816);
               end;
           OP_IDIV :
               Begin
-{$warning To complete IDIV opcode}              
+                 internalerror(20020816);
               end;
           OP_IMUL :
               Begin
@@ -551,11 +548,11 @@ Implementation
               end;
           OP_DIV :
               Begin
-{$warning DIV to complete}              
+                 internalerror(20020816);
               end;
           OP_IDIV :
               Begin
-{$warning IDIV to complete}              
+                 internalerror(20020816);
               end;
           OP_IMUL :
               Begin
@@ -1016,12 +1013,26 @@ Implementation
       
       end;
       
-    procedure tcg68k.g_save_standard_registers(list : taasmoutput);
+    procedure tcg68k.g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);
+      var
+        tosave : tregisterlist;
       begin
+         tosave:=std_saved_registers;
+         { only save the registers which are not used and must be saved }
+         tosave:=tosave*usedinproc;
+         if tosave<>[] then
+           list.concat(taicpu.op_reglist_reg(A_MOVEM,S_L,tosave,R_SPPUSH));
       end;
       
-    procedure tcg68k.g_restore_standard_registers(list : taasmoutput);
+    procedure tcg68k.g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);
+      var
+       torestore : tregisterset;
       begin
+         torestore:=std_saved_registers;
+         { should be intersected with used regs, no ? }
+         torestore:=torestore*usedinproc;
+         if torestore<>[] then
+           list.concat(taicpu.op_reg_reglist(A_MOVEM,S_L,R_SPPULL,torestore));
       end;
       
     procedure tcg68k.g_save_all_registers(list : taasmoutput);
@@ -1092,12 +1103,19 @@ Implementation
 
 begin
   cg := tcg68k.create;
-{  cg64 :=tcg64fppc.create;}
+  cg64 :=tcg64f32.create;
 end.
 
 { 
   $Log$
-  Revision 1.3  2002-08-15 08:13:54  carl
+  Revision 1.4  2002-08-16 14:24:59  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.3  2002/08/15 08:13:54  carl
     - a_load_sym_ofs_reg removed
     * loadvmt now calls loadaddr_ref_reg instead
 

+ 30 - 23
compiler/ncal.pas

@@ -1506,10 +1506,10 @@ implementation
          else
            resulttype:=restype;
 
-         { get a register for the return value }
+         { modify the exit code, in case of special cases }
          if (not is_void(resulttype.def)) then
           begin
-            if paramanager.ret_in_acc(resulttype.def) then
+            if paramanager.ret_in_reg(resulttype.def) then
              begin
                { wide- and ansistrings are returned in EAX    }
                { but they are imm. moved to a memory location }
@@ -1786,28 +1786,28 @@ implementation
     function Tcallnode.track_state_pass(exec_known:boolean):boolean;
 
     var hp:Tcallparanode;
-	value:Tnode;
+  value:Tnode;
 
     begin
-	track_state_pass:=false;
-	hp:=Tcallparanode(left);
-	while assigned(hp) do
-	    begin
-		if left.track_state_pass(exec_known) then
-		    begin
-			left.resulttype.def:=nil;
-			do_resulttypepass(left);
-		    end;
-		value:=aktstate.find_fact(hp.left);
-		if value<>nil then
-		    begin
-			track_state_pass:=true;
-			hp.left.destroy;
-			hp.left:=value.getcopy;
-			do_resulttypepass(hp.left);
-		    end;
-		hp:=Tcallparanode(hp.right);
-	    end;
+  track_state_pass:=false;
+  hp:=Tcallparanode(left);
+  while assigned(hp) do
+      begin
+    if left.track_state_pass(exec_known) then
+        begin
+      left.resulttype.def:=nil;
+      do_resulttypepass(left);
+        end;
+    value:=aktstate.find_fact(hp.left);
+    if value<>nil then
+        begin
+      track_state_pass:=true;
+      hp.left.destroy;
+      hp.left:=value.getcopy;
+      do_resulttypepass(hp.left);
+        end;
+    hp:=Tcallparanode(hp.right);
+      end;
     end;
 {$endif}
 
@@ -1904,7 +1904,14 @@ begin
 end.
 {
   $Log$
-  Revision 1.83  2002-07-20 11:57:53  florian
+  Revision 1.84  2002-08-16 14:24:57  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.83  2002/07/20 11:57:53  florian
     * types.pas renamed to defbase.pas because D6 contains a types
       unit so this would conflicts if D6 programms are compiled
     + Willamette/SSE2 instructions to assembler added

+ 82 - 27
compiler/ncgutil.pas

@@ -30,7 +30,7 @@ interface
       node,cpuinfo,
       cpubase,cpupara,
       aasmbase,aasmtai,aasmcpu,
-      cginfo,
+      cginfo,symbase,symdef,symtype,
       rgobj;
 
     type
@@ -65,27 +65,36 @@ interface
    procedure genimplicitunitinit(list : TAAsmoutput);
    procedure genimplicitunitfinal(list : TAAsmoutput);
 
-          {#
-              Allocate the buffers for exception management and setjmp environment.
-              Return a pointer to these buffers, send them to the utility routine
-              so they are registered, and then call setjmp.
+   {#
+      Allocate the buffers for exception management and setjmp environment.
+      Return a pointer to these buffers, send them to the utility routine
+      so they are registered, and then call setjmp.
 
-              Then compare the result of setjmp with 0, and if not equal
-              to zero, then jump to exceptlabel.
-
-              Also store the result of setjmp to a temporary space by calling g_save_exception_reason
-
-              It is to note that this routine may be called *after* the stackframe of a
-              routine has been called, therefore on machines where the stack cannot
-              be modified, all temps should be allocated on the heap instead of the
-              stack.
-          }
-          procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference;
-              a : aword; exceptlabel : tasmlabel);
-          procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference;
-           a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
+      Then compare the result of setjmp with 0, and if not equal
+      to zero, then jump to exceptlabel.
 
+      Also store the result of setjmp to a temporary space by calling g_save_exception_reason
 
+      It is to note that this routine may be called *after* the stackframe of a
+      routine has been called, therefore on machines where the stack cannot
+      be modified, all temps should be allocated on the heap instead of the
+      stack.
+    }
+    procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference;
+      a : aword; exceptlabel : tasmlabel);
+    procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference;
+      a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
+
+   {#
+      This routine returns the registers which will be used in
+      function results , depending on the return definition
+      type.
+      
+      An empty set can be returned if this function does not return
+      anything in registers.
+   }
+    function getfuncusedregisters(def : tdef): tregisterset;
+      
 
 implementation
 
@@ -96,7 +105,7 @@ implementation
     strings,
 {$endif}
     cutils,cclasses,globtype,globals,systems,verbose,
-    symbase,symconst,symtype,symsym,symdef,symtable,defbase,paramgr,
+    symconst,symsym,symtable,defbase,paramgr,
     fmodule,
     cgbase,regvars,
 {$ifdef GDB}
@@ -1039,7 +1048,8 @@ implementation
       end;
 
 
-    procedure handle_return_value(list:TAAsmoutput; inlined : boolean;var uses_acc,uses_acchi : boolean);
+
+    procedure handle_return_value(list:TAAsmoutput; inlined : boolean;var uses_acc,uses_acchi,uses_fpu : boolean);
       var
         href : treference;
         hreg : tregister;
@@ -1072,6 +1082,7 @@ implementation
                end;
              floatdef :
                begin
+                 uses_fpu := true;
                  cg.a_loadfpu_ref_reg(list,cgsize,href,FPU_RESULT_REG);
                end;
              else
@@ -1086,7 +1097,7 @@ implementation
            end;
          end;
       end;
-
+      
 
     procedure handle_fast_exit_return_value(list:TAAsmoutput);
       var
@@ -1124,6 +1135,43 @@ implementation
       end;
 
 
+    function getfuncusedregisters(def : tdef): tregisterset;
+     var
+       paramloc : tparalocation;
+       regset : tregisterset;
+     begin
+       regset:=[];
+       getfuncusedregisters:=[];
+       { if nothing is returned in registers,
+         its useless to continue on in this
+         routine
+       }  
+       if not paramanager.ret_in_reg(def) then
+         exit;
+       paramloc := paramanager.getfuncresultlocreg(def);
+       case paramloc.loc of 
+         LOC_FPUREGISTER, 
+         LOC_CFPUREGISTER, 
+{$ifdef SUPPORT_MMX}         
+         LOC_MMREGISTER, 
+         LOC_CMMREGISTER,
+{$endif}         
+         LOC_REGISTER,LOC_CREGISTER :
+             begin
+               regset := regset + [paramloc.register];
+               if ((paramloc.size in [OS_S64,OS_64]) and
+                  (sizeof(aword) < 8))
+               then
+                 begin
+                    regset := regset + [paramloc.registerhigh];
+                 end;
+             end;
+       else
+         internalerror(20020816);
+      end;
+      getfuncusedregisters:=regset;
+     end;
+
 
     procedure genentrycode(list : TAAsmoutput;
                            make_global:boolean;
@@ -1157,7 +1205,7 @@ implementation
         else
          { should we save edi,esi,ebx like C ? }
          if (po_savestdregs in aktprocdef.procoptions) then
-           cg.g_save_standard_registers(list);
+           cg.g_save_standard_registers(list,aktprocdef.usedregisters);
 
         { a constructor needs a help procedure }
         if (aktprocdef.proctypeoption=potype_constructor) then
@@ -1392,7 +1440,7 @@ implementation
         href : treference;
         usesacc,
         usesacchi,
-        usesself : boolean;
+        usesself,usesfpu : boolean;
         pd : tprocdef;
       begin
         if aktexit2label.is_used and
@@ -1524,7 +1572,7 @@ implementation
             (tfuncretsym(aktprocdef.funcretsym).refcount>1)) then
           begin
             if (aktprocdef.proctypeoption<>potype_constructor) then
-              handle_return_value(list,inlined,usesacc,usesacchi)
+              handle_return_value(list,inlined,usesacc,usesacchi,usesfpu)
             else
               begin
                 { successful constructor deletes the zero flag }
@@ -1571,7 +1619,7 @@ implementation
         else
          { should we restore edi ? }
          if (po_savestdregs in aktprocdef.procoptions) then
-           cg.g_restore_standard_registers(list);
+           cg.g_restore_standard_registers(list,aktprocdef.usedregisters);
 
         { remove stackframe }
         if not inlined then
@@ -1731,7 +1779,14 @@ implementation
 end.
 {
   $Log$
-  Revision 1.37  2002-08-15 15:15:55  carl
+  Revision 1.38  2002-08-16 14:24:57  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.37  2002/08/15 15:15:55  carl
     * jmpbuf size allocation for exceptions is now cpu specific (as it should)
     * more generic nodes for maths
     * several fixes for better m68k support

+ 86 - 3
compiler/paramgr.pas

@@ -39,6 +39,12 @@ unit paramgr;
        tparamanager = class
           {# Returns true if the return value can be put in accumulator }
           function ret_in_acc(def : tdef) : boolean;virtual;
+          {# Returns true if the return value is put in a register 
+             
+             Either a floating point register, or a general purpose
+             register.
+          }
+          function ret_in_reg(def : tdef) : boolean;virtual;
 
           {# Returns true if the return value is actually a parameter
              pointer.
@@ -70,6 +76,14 @@ unit paramgr;
             generating the wrappers for implemented interfaces.
           }
           function getselflocation(p : tabstractprocdef) : tparalocation;virtual;abstract;
+          {# 
+            Returns the location of the result if the result is in
+            a register, the register(s) return depend on the type of
+            the result. 
+            
+            @param(def The definition of the result type of the function)
+          }
+          function getfuncresultlocreg(def : tdef): tparalocation; virtual;
        end;
 
     procedure setparalocs(p : tprocdef);
@@ -81,10 +95,10 @@ unit paramgr;
   implementation
 
     uses
-       cpuinfo,
+       cpuinfo,globals,globtype,
        symconst,symbase,symsym,
        rgobj,
-       defbase;
+       defbase,cgbase,cginfo,verbose;
 
     { true if the return value is in accumulator (EAX for i386), D0 for 68k }
     function tparamanager.ret_in_acc(def : tdef) : boolean;
@@ -96,6 +110,12 @@ unit paramgr;
                      ((def.deftype=setdef) and (tsetdef(def).settype=smallset));
       end;
 
+    function tparamanager.ret_in_reg(def : tdef) : boolean;
+      begin
+        ret_in_reg:=ret_in_acc(def) or (def.deftype=floatdef);
+      end;
+    
+
 
     { true if uses a parameter as return value }
     function tparamanager.ret_in_param(def : tdef) : boolean;
@@ -147,6 +167,62 @@ unit paramgr;
            end;
          end;
       end;
+      
+    function tparamanager.getfuncresultlocreg(def : tdef): tparalocation; 
+      begin
+         fillchar(result,sizeof(tparalocation),0);
+         if is_void(def) then exit;
+         
+         result.size := def_cgsize(def);
+         case aktprocdef.rettype.def.deftype of
+           orddef,
+           enumdef :
+             begin
+               result.loc := LOC_REGISTER;
+               if result.size in [OS_64,OS_S64] then
+                begin
+                  result.registerhigh:=accumulatorhigh;
+                  result.register:=accumulator;
+                end
+               else
+                  result.register:=accumulator;
+             end;
+           floatdef :
+             begin
+               result.loc := LOC_FPUREGISTER;
+               if cs_fp_emulation in aktmoduleswitches then
+                  result.register := accumulator
+               else
+                  result.register := FPU_RESULT_REG;
+             end;
+          else
+             begin
+                if ret_in_acc(def) then
+                  begin
+                    result.loc := LOC_REGISTER;
+                    result.register := accumulator;
+                  end
+                else
+                   begin
+                     result.loc := LOC_REFERENCE;
+                     internalerror(2002081602);
+(*                     
+{$ifdef EXTDEBUG}
+                     { it is impossible to have the
+                       return value with an index register
+                       and a symbol!
+                     }
+                     if (ref.index <> R_NO) or (assigned(ref.symbol)) then
+                        internalerror(2002081602);
+{$endif}
+                     result.reference.index := ref.base;
+                     result.reference.offset := ref.offset;
+*)                     
+                   end;
+             end;
+          end;
+      end;
+      
 
     procedure setparalocs(p : tprocdef);
 
@@ -190,7 +266,14 @@ end.
 
 {
    $Log$
-   Revision 1.11  2002-08-12 15:08:40  carl
+   Revision 1.12  2002-08-16 14:24:58  carl
+     * issameref() to test if two references are the same (then emit no opcodes)
+     + ret_in_reg to replace ret_in_acc
+       (fix some register allocation bugs at the same time)
+     + save_std_register now has an extra parameter which is the
+       usedinproc registers
+
+   Revision 1.11  2002/08/12 15:08:40  carl
      + stab register indexes for powerpc (moved from gdb to cpubase)
      + tprocessor enumeration moved to cpuinfo
      + linker in target_info is now a class

+ 12 - 5
compiler/powerpc/cgcpu.pas

@@ -91,8 +91,8 @@ unit cgcpu;
         { that's the case, we can use rlwinm to do an AND operation        }
         function get_rlwi_const(a: longint; var l1, l2: longint): boolean;
 
-        procedure g_save_standard_registers(list : taasmoutput);override;
-        procedure g_restore_standard_registers(list : taasmoutput);override;
+        procedure g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
+        procedure g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
         procedure g_save_all_registers(list : taasmoutput);override;
         procedure g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);override;
 
@@ -698,12 +698,12 @@ const
         end;
 
 
-     procedure tcgppc.g_save_standard_registers(list : taasmoutput);
+     procedure tcgppc.g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);
        begin
          {$warning FIX ME}
        end;
 
-     procedure tcgppc.g_restore_standard_registers(list : taasmoutput);
+     procedure tcgppc.g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);
        begin
          {$warning FIX ME}
        end;
@@ -1666,7 +1666,14 @@ begin
 end.
 {
   $Log$
-  Revision 1.41  2002-08-15 08:13:54  carl
+  Revision 1.42  2002-08-16 14:24:59  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.41  2002/08/15 08:13:54  carl
     - a_load_sym_ofs_reg removed
     * loadvmt now calls loadaddr_ref_reg instead
 

+ 19 - 8
compiler/pstatmnt.pas

@@ -55,6 +55,7 @@ implementation
        pbase,pexpr,
        { codegen }
        rgobj,cgbase
+       ,ncgutil
        ,radirect
 {$ifdef i386}
   {$ifndef NoRa386Int}
@@ -1092,9 +1093,12 @@ implementation
               { update the symtablesize back to 0 if there were no locals }
               if not haslocals then
                symtablestack.datasize:=0;
-              { set the used flag for the return }
-              if paramanager.ret_in_acc(aktprocdef.rettype.def) then
-                 include(rg.usedinproc,accumulator);
+              { set the used registers depending on the function result }
+              if paramanager.ret_in_reg(aktprocdef.rettype.def) then
+                begin
+                  rg.usedinproc := rg.usedinproc + 
+                    getfuncusedregisters(aktprocdef.rettype.def);
+                end;
             end;
          { force the asm statement }
          if token<>_ASM then
@@ -1125,11 +1129,11 @@ implementation
             then
            OptimizeFramePointer(tasmnode(p));
 
-        { Flag the result as assigned when it is returned in the
-          accumulator or on the fpu stack }
+        { Flag the result as assigned when it is returned in a
+          register.
+        }  
         if assigned(aktprocdef.funcretsym) and
-           (is_fpu(aktprocdef.rettype.def) or
-           paramanager.ret_in_acc(aktprocdef.rettype.def)) then
+           paramanager.ret_in_reg(aktprocdef.rettype.def) then
           tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
 
         { because the END is already read we need to get the
@@ -1142,7 +1146,14 @@ implementation
 end.
 {
   $Log$
-  Revision 1.70  2002-08-11 14:32:27  peter
+  Revision 1.71  2002-08-16 14:24:58  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.70  2002/08/11 14:32:27  peter
     * renamed current_library to objectlibrary
 
   Revision 1.69  2002/08/11 13:24:12  peter

+ 18 - 9
compiler/psub.pas

@@ -106,8 +106,10 @@ implementation
               { insert in local symtable }
               symtablestack.insert(aktprocdef.funcretsym);
               akttokenpos:=storepos;
-              if paramanager.ret_in_acc(aktprocdef.rettype.def) or
-                 (aktprocdef.rettype.def.deftype=floatdef) then
+              { the result will be returned in a register, then setup
+                the temp. memory for the result
+              }  
+              if paramanager.ret_in_reg(aktprocdef.rettype.def) then
                 procinfo^.return_offset:=-tfuncretsym(aktprocdef.funcretsym).address;
               { insert result also if support is on }
               if (m_result in aktmodeswitches) then
@@ -130,18 +132,18 @@ implementation
          { because we don't know yet where the address is }
          if not is_void(aktprocdef.rettype.def) then
            begin
-              if paramanager.ret_in_acc(aktprocdef.rettype.def) or (aktprocdef.rettype.def.deftype=floatdef) then
+              if paramanager.ret_in_reg(aktprocdef.rettype.def) then
                 begin
                    { the space has been set in the local symtable }
                    procinfo^.return_offset:=-tfuncretsym(aktprocdef.funcretsym).address;
                    if ((procinfo^.flags and pi_operator)<>0) and
                       assigned(otsym) then
                      otsym.address:=-procinfo^.return_offset;
-                   { eax is modified by a function }
-                   include(rg.usedinproc,accumulator);
-                   if (sizeof(aword) < 8) and
-                      (is_64bitint(aktprocdef.rettype.def)) then
-                     include(rg.usedinproc,accumulatorhigh);
+                   { is the return result in registers? The
+                     set them as used in the routine
+                   }  
+                   rg.usedinproc := rg.usedinproc + 
+                      getfuncusedregisters(aktprocdef.rettype.def);
                 end;
            end;
 
@@ -814,7 +816,14 @@ implementation
 end.
 {
   $Log$
-  Revision 1.66  2002-08-11 14:32:27  peter
+  Revision 1.67  2002-08-16 14:24:59  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.66  2002/08/11 14:32:27  peter
     * renamed current_library to objectlibrary
 
   Revision 1.65  2002/08/11 13:24:13  peter

+ 9 - 2
compiler/rautils.pas

@@ -736,7 +736,7 @@ Begin
   if (not is_void(aktprocdef.rettype.def)) then
    begin
      if (m_tp7 in aktmodeswitches) and
-        paramanager.ret_in_acc(aktprocdef.rettype.def) then
+        paramanager.ret_in_reg(aktprocdef.rettype.def) then
        begin
          Message(asmr_e_cannot_use_RESULT_here);
          exit;
@@ -1592,7 +1592,14 @@ end;
 end.
 {
   $Log$
-  Revision 1.42  2002-08-13 18:01:52  carl
+  Revision 1.43  2002-08-16 14:24:59  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.42  2002/08/13 18:01:52  carl
     * rename swatoperands to swapoperands
     + m68k first compilable version (still needs a lot of testing):
         assembler generator, system information , inline

+ 10 - 4
compiler/symsym.pas

@@ -1296,9 +1296,8 @@ implementation
          address:=procinfo^.return_offset
         else
          begin
-           { allocate space in local if ret in acc or in fpu }
-           if paramanager.ret_in_acc(returntype.def) or
-              (returntype.def.deftype=floatdef) then
+           { allocate space in local if ret in register }
+           if paramanager.ret_in_reg(returntype.def) then
             begin
               l:=returntype.def.size;
               varalign:=size_2_align(l);
@@ -2672,7 +2671,14 @@ implementation
 end.
 {
   $Log$
-  Revision 1.50  2002-08-13 21:40:57  florian
+  Revision 1.51  2002-08-16 14:24:59  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.50  2002/08/13 21:40:57  florian
     * more fixes for ppc calling conventions
 
   Revision 1.49  2002/08/12 15:08:40  carl

+ 14 - 7
compiler/x86/cgx86.pas

@@ -117,8 +117,8 @@ unit cgx86;
         procedure g_call_destructor_helper(list : taasmoutput);override;
         procedure g_call_fail_helper(list : taasmoutput);override;
 {$endif}
-        procedure g_save_standard_registers(list : taasmoutput);override;
-        procedure g_restore_standard_registers(list : taasmoutput);override;
+        procedure g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
+        procedure g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);override;
         procedure g_save_all_registers(list : taasmoutput);override;
         procedure g_restore_all_registers(list : taasmoutput;selfused,accused,acchiused:boolean);override;
 
@@ -1565,20 +1565,20 @@ unit cgx86;
 {$endif}
 
 
-    procedure tcgx86.g_save_standard_registers(list : taasmoutput);
+    procedure tcgx86.g_save_standard_registers(list : taasmoutput; usedinproc : tregisterset);
       begin
-        if (R_EBX in aktprocdef.usedregisters) then
+        if (R_EBX in usedinproc) then
           list.concat(Taicpu.Op_reg(A_PUSH,S_L,R_EBX));
         list.concat(Taicpu.Op_reg(A_PUSH,S_L,R_ESI));
         list.concat(Taicpu.Op_reg(A_PUSH,S_L,R_EDI));
       end;
 
 
-    procedure tcgx86.g_restore_standard_registers(list : taasmoutput);
+    procedure tcgx86.g_restore_standard_registers(list : taasmoutput; usedinproc : tregisterset);
       begin
         list.concat(Taicpu.Op_reg(A_POP,S_L,R_EDI));
         list.concat(Taicpu.Op_reg(A_POP,S_L,R_ESI));
-        if (R_EBX in aktprocdef.usedregisters) then
+        if (R_EBX in usedinproc) then
          list.concat(Taicpu.Op_reg(A_POP,S_L,R_EBX));
       end;
 
@@ -1644,7 +1644,14 @@ unit cgx86;
 end.
 {
   $Log$
-  Revision 1.10  2002-08-15 08:13:54  carl
+  Revision 1.11  2002-08-16 14:25:00  carl
+    * issameref() to test if two references are the same (then emit no opcodes)
+    + ret_in_reg to replace ret_in_acc
+      (fix some register allocation bugs at the same time)
+    + save_std_register now has an extra parameter which is the
+      usedinproc registers
+
+  Revision 1.10  2002/08/15 08:13:54  carl
     - a_load_sym_ofs_reg removed
     * loadvmt now calls loadaddr_ref_reg instead