فهرست منبع

* 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
 
     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