Selaa lähdekoodia

* make sparc para manager quite similar to ppc one to help
copying evolutions.
+ Add support to var args in registers. need to be verfied as it
was just copying ppc's one

mazen 21 vuotta sitten
vanhempi
commit
5962aeb34e
1 muutettua tiedostoa jossa 229 lisäystä ja 100 poistoa
  1. 229 100
      compiler/sparc/cpupara.pas

+ 229 - 100
compiler/sparc/cpupara.pas

@@ -25,9 +25,11 @@ unit cpupara;
 interface
 
     uses
-      cpubase,cgbase,
-      aasmtai,globtype,
-      symconst,symtype,symdef,paramgr;
+      globtype,
+      cclasses,
+      aasmtai,
+      cpubase,cpuinfo,
+      symconst,symbase,symtype,symdef,paramgr,cgbase;
 
     type
       TSparcParaManager=class(TParaManager)
@@ -41,52 +43,22 @@ interface
         function  getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override;
         procedure allocparaloc(list: taasmoutput; const loc: tparalocation);override;
         procedure freeparaloc(list: taasmoutput; const loc: tparalocation);override;
-        function  create_paraloc_info(p:TAbstractProcDef; side: tcallercallee):longint;override;
+        function  create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override;
+        function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargspara):longint;override;
         procedure splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);override;
+         private
+           procedure init_values(var curintreg :tsuperregister; var cur_stack_offset: aWord);
+           function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; firstpara: tparaitem;
+               var curintreg: tsuperregister; var cur_stack_offset: aword):longint;
       end;
 
-
 implementation
 
     uses
       verbose,
       defutil,cgobj;
 
-    function tsparcparamanager.copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
-      begin
-        result:=false;
-      end;
-
-
-    { true if a parameter is too large to copy and only the address is pushed }
-    function tsparcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
-      begin
-        result:=false;
-        { var,out always require address }
-        if varspez in [vs_var,vs_out] then
-          begin
-            result:=true;
-            exit;
-          end;
-        case def.deftype of
-          recorddef,
-          arraydef,
-          variantdef,
-          formaldef :
-            push_addr_param:=true;
-          objectdef :
-            result:=is_object(def);
-          stringdef :
-            result:=(tstringdef(def).string_typ in [st_shortstring,st_longstring]);
-          procvardef :
-            result:=(po_methodpointer in tprocvardef(def).procoptions);
-          setdef :
-            result:=(tsetdef(def).settype<>smallset);
-        end;
-      end;
-
-
-    function tsparcparamanager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
+    function TSparcParaManager.get_volatile_registers_int(calloption : tproccalloption):TCpuRegisterSet;
       begin
         result:=[RS_G1];
       end;
@@ -125,38 +97,178 @@ implementation
       end;
 
 
-    procedure tsparcparamanager.allocparaloc(list: taasmoutput; const loc: tparalocation);
+    function getparaloc(p : tdef) : tcgloc;
+
       begin
-        if (loc.loc=LOC_REFERENCE) and
-           (loc.low_in_reg) then
-          cg.GetExplicitRegister(list,loc.lowreg);
-        inherited allocparaloc(list,loc);
+         { Later, the LOC_REFERENCE is in most cases changed into LOC_REGISTER
+           if push_addr_param for the def is true
+         }
+         case p.deftype of
+            orddef:
+              getparaloc:=LOC_REGISTER;
+            floatdef:
+              getparaloc:=LOC_FPUREGISTER;
+            enumdef:
+              getparaloc:=LOC_REGISTER;
+            pointerdef:
+              getparaloc:=LOC_REGISTER;
+            formaldef:
+              getparaloc:=LOC_REGISTER;
+            classrefdef:
+              getparaloc:=LOC_REGISTER;
+            recorddef:
+              getparaloc:=LOC_REFERENCE;
+            objectdef:
+              if is_object(p) then
+                getparaloc:=LOC_REFERENCE
+              else
+                getparaloc:=LOC_REGISTER;
+            stringdef:
+              if is_shortstring(p) or is_longstring(p) then
+                getparaloc:=LOC_REFERENCE
+              else
+                getparaloc:=LOC_REGISTER;
+            procvardef:
+              if (po_methodpointer in tprocvardef(p).procoptions) then
+                getparaloc:=LOC_REFERENCE
+              else
+                getparaloc:=LOC_REGISTER;
+            filedef:
+              getparaloc:=LOC_REGISTER;
+            arraydef:
+              getparaloc:=LOC_REFERENCE;
+            setdef:
+              if is_smallset(p) then
+                getparaloc:=LOC_REGISTER
+              else
+                getparaloc:=LOC_REFERENCE;
+            variantdef:
+              getparaloc:=LOC_REFERENCE;
+            { avoid problems with errornous definitions }
+            errordef:
+              getparaloc:=LOC_REGISTER;
+            else
+              internalerror(2002071001);
+         end;
+      end;
+    function tsparcparamanager.copy_value_on_stack(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
+      begin
+        result:=false;
       end;
 
 
-    procedure tsparcparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
+    { true if a parameter is too large to copy and only the address is pushed }
+    function tsparcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
       begin
-        if (loc.loc=LOC_REFERENCE) and
-           (loc.low_in_reg) then
-          cg.UnGetRegister(list,loc.lowreg);
-        inherited freeparaloc(list,loc);
+        result:=false;
+        { var,out always require address }
+        if varspez in [vs_var,vs_out] then
+          begin
+            result:=true;
+            exit;
+          end;
+        case def.deftype of
+          recorddef,
+          arraydef,
+          variantdef,
+          formaldef :
+            push_addr_param:=true;
+          objectdef :
+            result:=is_object(def);
+          stringdef :
+            result:=(tstringdef(def).string_typ in [st_shortstring,st_longstring]);
+          procvardef :
+            result:=(po_methodpointer in tprocvardef(def).procoptions);
+          setdef :
+            result:=(tsetdef(def).settype<>smallset);
+        end;
+      end;
+
+
+    procedure TSparcParaManager.init_values(var curintreg: tsuperregister; var cur_stack_offset: aWord);
+      begin
+        CurIntReg:=RS_O0;
+        cur_stack_offset:=92;
       end;
 
 
     function TSparcParaManager.create_paraloc_info(p:TAbstractProcDef; side: tcallercallee):longint;
       var
+        paraloc : tparalocation;
+        stack_offset : aWord;
         nextintreg : tsuperregister;
-        stack_offset : longint;
         hp : tparaitem;
         is_64bit : boolean;
-        paraloc : tparalocation;
       begin
-        nextintreg:=RS_O0;
+        init_values(NextIntReg,stack_offset);
         { Nested procedures have the parent framepoint in o0 }
         if p.parast.symtablelevel>normal_function_level then
           inc(NextIntReg);
-        stack_offset:=92;
-        hp:=TParaItem(p.para.First);
+        result := create_paraloc_info_intern(p,side,TParaItem(p.para.First),NextIntReg,stack_offset);
+
+        { Function return }
+        fillchar(paraloc,sizeof(tparalocation),0);
+        paraloc.size:=def_cgsize(p.rettype.def);
+        paraloc.Alignment:= std_param_align;
+        { Return in FPU register? }
+        if p.rettype.def.deftype=floatdef then
+          begin
+            paraloc.loc:=LOC_FPUREGISTER;
+            paraloc.register:=NR_FPU_RESULT_REG;
+          end
+        else
+         { Return in register? }
+         if not ret_in_param(p.rettype.def,p.proccalloption) then
+          begin
+            paraloc.loc:=LOC_REGISTER;
+{$ifndef cpu64bit}
+            if paraloc.size in [OS_64,OS_S64] then
+             begin
+               paraloc.lochigh:=LOC_REGISTER;
+               if side=callerside then
+                 paraloc.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
+               else
+                 paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+               if side=callerside then
+                 paraloc.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
+               else
+                 paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+             end
+            else
+{$endif cpu64bit}
+             begin
+               if side=callerside then
+                 paraloc.register:=NR_FUNCTION_RESULT_REG
+               else
+                 paraloc.register:=NR_FUNCTION_RETURN_REG;
+             end;
+          end
+        else
+          begin
+            paraloc.loc:=LOC_REFERENCE;
+          end;
+        p.funcret_paraloc[side]:=paraloc;
+        { Size on stack is not used }
+        result:=0;
+      end;
+
+
+
+    function TSparcParaManager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; firstpara: tparaitem;
+               var curintreg: tsuperregister; var cur_stack_offset: aword):longint;
+      var
+         stack_offset: aword;
+         nextintreg : tsuperregister;
+         paradef : tdef;
+         paraloc : tparalocation;
+         hp : tparaitem;
+         loc : tcgloc;
+         is_64bit: boolean;
+      begin
+         result:=0;
+         nextintreg := curintreg;
+         stack_offset := cur_stack_offset;
+         hp:=firstpara;
         while assigned(hp) do
           begin
             fillchar(paraloc,sizeof(paraloc),0);
@@ -222,54 +334,28 @@ implementation
               end;
             hp:=TParaItem(hp.Next);
           end;
+      end;
 
-        { Function return }
-        fillchar(paraloc,sizeof(tparalocation),0);
-        paraloc.size:=def_cgsize(p.rettype.def);
-        paraloc.Alignment:= std_param_align;
-        { Return in FPU register? }
-        if p.rettype.def.deftype=floatdef then
-          begin
-            paraloc.loc:=LOC_FPUREGISTER;
-            paraloc.register:=NR_FPU_RESULT_REG;
-          end
-        else
-         { Return in register? }
-         if not ret_in_param(p.rettype.def,p.proccalloption) then
-          begin
-            paraloc.loc:=LOC_REGISTER;
-{$ifndef cpu64bit}
-            if paraloc.size in [OS_64,OS_S64] then
-             begin
-               paraloc.lochigh:=LOC_REGISTER;
-               if side=callerside then
-                 paraloc.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG
-               else
-                 paraloc.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
-               if side=callerside then
-                 paraloc.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG
-               else
-                 paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
-             end
-            else
-{$endif cpu64bit}
-             begin
-               if side=callerside then
-                 paraloc.register:=NR_FUNCTION_RESULT_REG
-               else
-                 paraloc.register:=NR_FUNCTION_RETURN_REG;
-             end;
-          end
-        else
-          begin
-            paraloc.loc:=LOC_REFERENCE;
-          end;
-        p.funcret_paraloc[side]:=paraloc;
-        { Size on stack is not used }
-        result:=0;
+
+
+
+    procedure tsparcparamanager.allocparaloc(list: taasmoutput; const loc: tparalocation);
+      begin
+        if (loc.loc=LOC_REFERENCE) and
+           (loc.low_in_reg) then
+          cg.GetExplicitRegister(list,loc.lowreg);
+        inherited allocparaloc(list,loc);
       end;
 
 
+    procedure tsparcparamanager.freeparaloc(list: taasmoutput; const loc: tparalocation);
+      begin
+        if (loc.loc=LOC_REFERENCE) and
+           (loc.low_in_reg) then
+          cg.UnGetRegister(list,loc.lowreg);
+        inherited freeparaloc(list,loc);
+      end;
+
     procedure tsparcparamanager.splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);
       begin
         { Word 0 is in register, word 1 is in reference }
@@ -291,13 +377,56 @@ implementation
         else
           inherited splitparaloc64(locpara,loclopara,lochipara);
       end;
+    function TSparcParaManager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargspara):longint;
+      var
+        cur_stack_offset: aword;
+        parasize, l: longint;
+        curintreg, firstfloatreg, curfloatreg, curmmreg: tsuperregister;
+        hp: tparaitem;
+        paraloc: tparalocation;
+      begin
+        init_values(curintreg,cur_stack_offset);
+        firstfloatreg:=curfloatreg;
+
+        result := create_paraloc_info_intern(p,callerside,tparaitem(p.para.first),curintreg,cur_stack_offset);
+        if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
+          { just continue loading the parameters in the registers }
+          result := create_paraloc_info_intern(p,callerside,tparaitem(varargspara.first),curintreg,cur_stack_offset)
+        else
+          begin
+            hp := tparaitem(varargspara.first);
+            parasize := cur_stack_offset;
+            while assigned(hp) do
+              begin
+                paraloc.size:=def_cgsize(hp.paratype.def);
+                paraloc.lochigh:=LOC_INVALID;
+                paraloc.loc:=LOC_REFERENCE;
+                paraloc.alignment:=4;
+                paraloc.reference.index:=NR_STACK_POINTER_REG;
+                l:=push_size(hp.paratyp,hp.paratype.def,p.proccalloption);
+                paraloc.reference.offset:=parasize;
+                parasize:=parasize+l;
+                hp.paraloc[callerside]:=paraloc;
+                hp:=tparaitem(hp.next);
+              end;
+            result := parasize;
+          end;
+        if curfloatreg<>firstfloatreg then
+          include(varargspara.varargsinfo,va_uses_float_reg);
+      end;
 
 begin
    ParaManager:=TSparcParaManager.create;
 end.
 {
   $Log$
-  Revision 1.37  2004-03-09 13:05:49  mazen
+  Revision 1.38  2004-03-15 14:39:56  mazen
+  * make sparc para manager quite similar to ppc one to help
+    copying evolutions.
+  + Add support to var args in registers. need to be verfied as it
+    was just copying ppc's one
+
+  Revision 1.37  2004/03/09 13:05:49  mazen
   + give location for 64bit to fix IE 200402061
 
   Revision 1.36  2004/02/25 14:25:47  mazen