فهرست منبع

* 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 سال پیش
والد
کامیت
5962aeb34e
1فایلهای تغییر یافته به همراه229 افزوده شده و 100 حذف شده
  1. 229 100
      compiler/sparc/cpupara.pas

+ 229 - 100
compiler/sparc/cpupara.pas

@@ -25,9 +25,11 @@ unit cpupara;
 interface
 interface
 
 
     uses
     uses
-      cpubase,cgbase,
-      aasmtai,globtype,
-      symconst,symtype,symdef,paramgr;
+      globtype,
+      cclasses,
+      aasmtai,
+      cpubase,cpuinfo,
+      symconst,symbase,symtype,symdef,paramgr,cgbase;
 
 
     type
     type
       TSparcParaManager=class(TParaManager)
       TSparcParaManager=class(TParaManager)
@@ -41,52 +43,22 @@ interface
         function  getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override;
         function  getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override;
         procedure allocparaloc(list: taasmoutput; const loc: tparalocation);override;
         procedure allocparaloc(list: taasmoutput; const loc: tparalocation);override;
         procedure freeparaloc(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;
         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;
       end;
 
 
-
 implementation
 implementation
 
 
     uses
     uses
       verbose,
       verbose,
       defutil,cgobj;
       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
       begin
         result:=[RS_G1];
         result:=[RS_G1];
       end;
       end;
@@ -125,38 +97,178 @@ implementation
       end;
       end;
 
 
 
 
-    procedure tsparcparamanager.allocparaloc(list: taasmoutput; const loc: tparalocation);
+    function getparaloc(p : tdef) : tcgloc;
+
       begin
       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;
       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
       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;
       end;
 
 
 
 
     function TSparcParaManager.create_paraloc_info(p:TAbstractProcDef; side: tcallercallee):longint;
     function TSparcParaManager.create_paraloc_info(p:TAbstractProcDef; side: tcallercallee):longint;
       var
       var
+        paraloc : tparalocation;
+        stack_offset : aWord;
         nextintreg : tsuperregister;
         nextintreg : tsuperregister;
-        stack_offset : longint;
         hp : tparaitem;
         hp : tparaitem;
         is_64bit : boolean;
         is_64bit : boolean;
-        paraloc : tparalocation;
       begin
       begin
-        nextintreg:=RS_O0;
+        init_values(NextIntReg,stack_offset);
         { Nested procedures have the parent framepoint in o0 }
         { Nested procedures have the parent framepoint in o0 }
         if p.parast.symtablelevel>normal_function_level then
         if p.parast.symtablelevel>normal_function_level then
           inc(NextIntReg);
           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
         while assigned(hp) do
           begin
           begin
             fillchar(paraloc,sizeof(paraloc),0);
             fillchar(paraloc,sizeof(paraloc),0);
@@ -222,54 +334,28 @@ implementation
               end;
               end;
             hp:=TParaItem(hp.Next);
             hp:=TParaItem(hp.Next);
           end;
           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;
       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);
     procedure tsparcparamanager.splitparaloc64(const locpara:tparalocation;var loclopara,lochipara:tparalocation);
       begin
       begin
         { Word 0 is in register, word 1 is in reference }
         { Word 0 is in register, word 1 is in reference }
@@ -291,13 +377,56 @@ implementation
         else
         else
           inherited splitparaloc64(locpara,loclopara,lochipara);
           inherited splitparaloc64(locpara,loclopara,lochipara);
       end;
       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
 begin
    ParaManager:=TSparcParaManager.create;
    ParaManager:=TSparcParaManager.create;
 end.
 end.
 {
 {
   $Log$
   $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
   + give location for 64bit to fix IE 200402061
 
 
   Revision 1.36  2004/02/25 14:25:47  mazen
   Revision 1.36  2004/02/25 14:25:47  mazen