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

* hopefully fixed varargs (both Pascal- and C-style)

Jonas Maebe 21 лет назад
Родитель
Сommit
6bab64590e
1 измененных файлов с 121 добавлено и 76 удалено
  1. 121 76
      compiler/powerpc/cpupara.pas

+ 121 - 76
compiler/powerpc/cpupara.pas

@@ -31,7 +31,7 @@ unit cpupara;
        globtype,
        cclasses,
        aasmtai,
-       cpubase,
+       cpubase,cpuinfo,
        symconst,symbase,symtype,symdef,paramgr,cgbase;
 
     type
@@ -42,15 +42,19 @@ unit cpupara;
           function getintparaloc(calloption : tproccalloption; nr : longint) : tparalocation;override;
           function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
           function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tlinkedlist):longint;override;
+         private
+           procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+           function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; firstpara: tparaitem;
+               var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
        end;
 
   implementation
 
     uses
        verbose,systems,
-       cpuinfo,procinfo,
+       procinfo,
        rgobj,
-       defutil,symsym;
+       defutil,symsym,cpupi;
 
 
     function tppcparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;
@@ -176,13 +180,75 @@ unit cpupara;
         end;
       end;
 
+
+    procedure tppcparamanager.init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword);
+      begin
+        case target_info.abi of
+          abi_powerpc_aix:
+            cur_stack_offset:=24;
+          abi_powerpc_sysv:
+            cur_stack_offset:=8;
+          else
+            internalerror(2003051901);
+        end;
+        curintreg:=RS_R3;
+        curfloatreg:=RS_F1;
+        curmmreg:=RS_M1;
+      end;
+
+
     function tppcparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;
 
       var
+        paraloc : tparalocation;
+        cur_stack_offset: aword;
+        curintreg, curfloatreg, curmmreg: tsuperregister;
+      begin
+        init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+        result := create_paraloc_info_intern(p,side,tparaitem(p.para.first),curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+        { Function return }
+        fillchar(paraloc,sizeof(tparalocation),0);
+        paraloc.alignment:= std_param_align;
+        paraloc.size:=def_cgsize(p.rettype.def);
+        { 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.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
+               paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
+             end
+            else
+{$endif cpu64bit}
+             paraloc.register:=NR_FUNCTION_RETURN_REG;
+          end
+        else
+          begin
+            paraloc.loc:=LOC_REFERENCE;
+          end;
+        p.funcret_paraloc[side]:=paraloc;
+      end;
+
+
+
+    function tppcparamanager.create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; firstpara: tparaitem;
+               var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint;
+      var
+         stack_offset: aword;
          nextintreg,nextfloatreg,nextmmreg : tsuperregister;
          paradef : tdef;
          paraloc : tparalocation;
-         stack_offset : aword;
          hp : tparaitem;
          loc : tcgloc;
          is_64bit: boolean;
@@ -209,25 +275,25 @@ unit cpupara;
 
       begin
          result:=0;
-         nextintreg:=RS_R3;
-         nextfloatreg:=RS_F1;
-         nextmmreg:=RS_M1;
-         case target_info.abi of
-           abi_powerpc_aix:
-             stack_offset:=24;
-           abi_powerpc_sysv:
-             stack_offset:=8;
-           else
-             internalerror(2003051901);
-         end;
+         nextintreg := curintreg;
+         nextfloatreg := curfloatreg;
+         nextmmreg := curmmreg;
+         stack_offset := cur_stack_offset;
 
-         { frame pointer for nested procedures? }
-         { inc(nextintreg);                     }
-         { constructor? }
-         { destructor? }
-         hp:=tparaitem(p.para.first);
+         hp:=firstpara;
          while assigned(hp) do
            begin
+              { currently only support C-style array of const }
+              if (p.proccalloption in [pocall_cdecl,pocall_cppdecl]) and
+                 is_array_of_const(hp.paratype.def) then
+                begin
+                  { hack: the paraloc must be valid, but is not actually used }
+                  hp.paraloc[side].loc := LOC_REGISTER;
+                  hp.paraloc[side].register := NR_R0;
+                  hp.paraloc[side].size := OS_ADDR;
+                  break;
+                end;
+                
               if (hp.paratyp in [vs_var,vs_out]) then
                 begin
                   paradef := voidpointertype.def;
@@ -327,69 +393,45 @@ unit cpupara;
               hp.paraloc[side]:=paraloc;
               hp:=tparaitem(hp.next);
            end;
-
-        { Function return }
-        fillchar(paraloc,sizeof(tparalocation),0);
-        paraloc.alignment:= std_param_align;
-        paraloc.size:=def_cgsize(p.rettype.def);
-        { 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.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG;
-               paraloc.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG;
-             end
-            else
-{$endif cpu64bit}
-             paraloc.register:=NR_FUNCTION_RETURN_REG;
-          end
-        else
-          begin
-            paraloc.loc:=LOC_REFERENCE;
-          end;
-        p.funcret_paraloc[side]:=paraloc;
+         curintreg:=nextintreg;
+         curfloatreg:=nextfloatreg;
+         curmmreg:=nextmmreg;
+         cur_stack_offset:=stack_offset;
       end;
 
 
     function tppcparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tlinkedlist):longint;
-      {$warning fixme!!!! tppcparamanager.create_varargs_paraloc_info}
       var
-        hp : tparaitem;
-        paraloc : tparalocation;
-        l,
-        parasize : longint;
+        cur_stack_offset: aword;
+        parasize, l: longint;
+        curintreg, curfloatreg, curmmreg: tsuperregister;
+        hp: tparaitem;
+        paraloc: tparalocation;
       begin
-        parasize:=0;
-        { Retrieve last know info from normal parameters }
-        hp:=tparaitem(p.para.last);
-        if assigned(hp) then
-          parasize:=hp.paraloc[callerside].reference.offset;
-        { Assign varargs }
-        hp:=tparaitem(varargspara.first);
-        while assigned(hp) do
+        init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset);
+
+        result := create_paraloc_info_intern(p,callerside,tparaitem(p.para.first),curintreg,curfloatreg,curmmreg,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,curfloatreg,curmmreg,cur_stack_offset)
+        else
           begin
-            paraloc.size:=def_cgsize(hp.paratype.def);
-            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);
+            hp := tparaitem(varargspara.first);
+            parasize := cur_stack_offset;
+            while assigned(hp) do
+              begin
+                paraloc.size:=def_cgsize(hp.paratype.def);
+                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;
-        { We need to return the size allocated }
-        result:=parasize;
       end;
 
 
@@ -398,7 +440,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.53  2003-12-16 21:49:47  florian
+  Revision 1.54  2003-12-28 15:33:06  jonas
+    * hopefully fixed varargs (both Pascal- and C-style)
+
+  Revision 1.53  2003/12/16 21:49:47  florian
     * fixed ppc compilation
 
   Revision 1.52  2003/12/07 22:35:05  florian