Quellcode durchsuchen

* multiple location support for i386 a_param_ref
* remove a_param_copy_ref for i386

peter vor 20 Jahren
Ursprung
Commit
b9ca478f50
8 geänderte Dateien mit 513 neuen und 393 gelöschten Zeilen
  1. 8 2
      compiler/cg64f32.pas
  2. 213 208
      compiler/cgobj.pas
  3. 119 71
      compiler/i386/cgcpu.pas
  4. 126 49
      compiler/i386/cpupara.pas
  5. 10 37
      compiler/ncgcal.pas
  6. 18 9
      compiler/ncgutil.pas
  7. 5 16
      compiler/parabase.pas
  8. 14 1
      compiler/paramgr.pas

+ 8 - 2
compiler/cg64f32.pas

@@ -35,7 +35,7 @@ unit cg64f32;
        aasmbase,aasmtai,aasmcpu,
        cpubase,cpupara,
        cgbase,cgobj,parabase,cgutils,
-       node,symtype
+       symtype
        ;
 
     type
@@ -124,10 +124,12 @@ unit cg64f32;
           cgparahi.size:=OS_S32
         else
           cgparahi.size:=OS_32;
+        cgparahi.intsize:=4;
         cgparahi.alignment:=cgpara.alignment;
         paralochi:=cgparahi.add_location;
         cgparalo.reset;
         cgparalo.size:=OS_32;
+        cgparalo.intsize:=4;
         cgparalo.alignment:=cgpara.alignment;
         paraloclo:=cgparalo.add_location;
         { 2 parameter fields? }
@@ -779,7 +781,11 @@ unit cg64f32;
 end.
 {
   $Log$
-  Revision 1.66  2004-12-03 15:58:11  peter
+  Revision 1.67  2005-01-18 22:19:20  peter
+    * multiple location support for i386 a_param_ref
+    * remove a_param_copy_ref for i386
+
+  Revision 1.66  2004/12/03 15:58:11  peter
     * LOC_CREGISTER fix
 
   Revision 1.65  2004/10/31 21:45:02  peter

+ 213 - 208
compiler/cgobj.pas

@@ -118,9 +118,9 @@ unit cgobj;
 
              @param(size size of the operand in the register)
              @param(r register source of the operand)
-             @param(paraloc where the parameter will be stored)
+             @param(cgpara where the parameter will be stored)
           }
-          procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const paraloc : TCGPara);virtual;
+          procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : TCGPara);virtual;
           {# Pass a parameter, which is a constant, to a routine.
 
              A generic version is provided. This routine should
@@ -129,9 +129,9 @@ unit cgobj;
 
              @param(size size of the operand in constant)
              @param(a value of constant to send)
-             @param(paraloc where the parameter will be stored)
+             @param(cgpara where the parameter will be stored)
           }
-          procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : TCGPara);virtual;
+          procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : TCGPara);virtual;
           {# Pass the value of a parameter, which is located in memory, to a routine.
 
              A generic version is provided. This routine should
@@ -140,9 +140,9 @@ unit cgobj;
 
              @param(size size of the operand in constant)
              @param(r Memory reference of value to send)
-             @param(paraloc where the parameter will be stored)
+             @param(cgpara where the parameter will be stored)
           }
-          procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : TCGPara);virtual;
+          procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : TCGPara);virtual;
           {# Pass the value of a parameter, which can be located either in a register or memory location,
              to a routine.
 
@@ -150,9 +150,9 @@ unit cgobj;
 
              @param(l location of the operand to send)
              @param(nr parameter number (starting from one) of routine (from left to right))
-             @param(paraloc where the parameter will be stored)
+             @param(cgpara where the parameter will be stored)
           }
-          procedure a_param_loc(list : taasmoutput;const l : tlocation;const paraloc : TCGPara);
+          procedure a_param_loc(list : taasmoutput;const l : tlocation;const cgpara : TCGPara);
           {# Pass the address of a reference to a routine. This routine
              will calculate the address of the reference, and pass this
              calculated address as a parameter.
@@ -164,10 +164,10 @@ unit cgobj;
              @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 paraloc : TCGPara);virtual;
+          procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const cgpara : TCGPara);virtual;
 
-          { Copies a whole memory block to the stack, the paraloc must be a memory location }
-          procedure a_param_copy_ref(list : taasmoutput;size : aint;const r : treference;const paraloc : TCGPara);
+          { Copies a whole memory block to the stack, the cgpara must be a memory location }
+          procedure a_param_copy_ref(list : taasmoutput;size : aint;const r : treference;const cgpara : TCGPara);virtual;
           { 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
@@ -214,8 +214,8 @@ unit cgobj;
           procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); virtual; abstract;
           procedure a_loadfpu_loc_reg(list: taasmoutput; const loc: tlocation; const reg: tregister);
           procedure a_loadfpu_reg_loc(list: taasmoutput; size: tcgsize; const reg: tregister; const loc: tlocation);
-          procedure a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const paraloc : TCGPara);virtual;
-          procedure a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const paraloc : TCGPara);virtual;
+          procedure a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const cgpara : TCGPara);virtual;
+          procedure a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const cgpara : TCGPara);virtual;
 
           { vector register move instructions }
           procedure a_loadmm_reg_reg(list: taasmoutput; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); virtual; abstract;
@@ -223,9 +223,9 @@ unit cgobj;
           procedure a_loadmm_reg_ref(list: taasmoutput; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle); virtual; abstract;
           procedure a_loadmm_loc_reg(list: taasmoutput; size: tcgsize; const loc: tlocation; const reg: tregister;shuffle : pmmshuffle);
           procedure a_loadmm_reg_loc(list: taasmoutput; size: tcgsize; const reg: tregister; const loc: tlocation;shuffle : pmmshuffle);
-          procedure a_parammm_reg(list: taasmoutput; size: tcgsize; reg: tregister;const paraloc : TCGPara;shuffle : pmmshuffle); virtual;
-          procedure a_parammm_ref(list: taasmoutput; size: tcgsize; const ref: treference;const paraloc : TCGPara;shuffle : pmmshuffle); virtual;
-          procedure a_parammm_loc(list: taasmoutput; const loc: tlocation; const paraloc : TCGPara;shuffle : pmmshuffle); virtual;
+          procedure a_parammm_reg(list: taasmoutput; size: tcgsize; reg: tregister;const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
+          procedure a_parammm_ref(list: taasmoutput; size: tcgsize; const ref: treference;const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
+          procedure a_parammm_loc(list: taasmoutput; const loc: tlocation; const cgpara : TCGPara;shuffle : pmmshuffle); virtual;
           procedure a_opmm_reg_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle); virtual;abstract;
           procedure a_opmm_ref_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); virtual;
           procedure a_opmm_loc_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const loc: tlocation; reg: tregister;shuffle : pmmshuffle); virtual;
@@ -709,18 +709,18 @@ implementation
           for better code generation these methods should be overridden
 ******************************************************************************}
 
-    procedure tcg.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const paraloc : TCGPara);
+    procedure tcg.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : TCGPara);
       var
          ref : treference;
       begin
-         paraloc.check_simple_location;
-         case paraloc.location^.loc of
+         cgpara.check_simple_location;
+         case cgpara.location^.loc of
             LOC_REGISTER,LOC_CREGISTER:
-              a_load_reg_reg(list,size,paraloc.location^.size,r,paraloc.location^.register);
+              a_load_reg_reg(list,size,cgpara.location^.size,r,cgpara.location^.register);
             LOC_REFERENCE,LOC_CREFERENCE:
               begin
-                 reference_reset_base(ref,paraloc.location^.reference.index,paraloc.location^.reference.offset);
-                 a_load_reg_ref(list,size,paraloc.location^.size,r,ref);
+                 reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
+                 a_load_reg_ref(list,size,cgpara.location^.size,r,ref);
               end
             else
               internalerror(2002071004);
@@ -728,18 +728,18 @@ implementation
       end;
 
 
-    procedure tcg.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const paraloc : TCGPara);
+    procedure tcg.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : TCGPara);
       var
          ref : treference;
       begin
-         paraloc.check_simple_location;
-         case paraloc.location^.loc of
+         cgpara.check_simple_location;
+         case cgpara.location^.loc of
             LOC_REGISTER,LOC_CREGISTER:
-              a_load_const_reg(list,paraloc.location^.size,a,paraloc.location^.register);
+              a_load_const_reg(list,cgpara.location^.size,a,cgpara.location^.register);
             LOC_REFERENCE,LOC_CREFERENCE:
               begin
-                 reference_reset_base(ref,paraloc.location^.reference.index,paraloc.location^.reference.offset);
-                 a_load_const_ref(list,paraloc.location^.size,a,ref);
+                 reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
+                 a_load_const_ref(list,cgpara.location^.size,a,ref);
               end
             else
               internalerror(2002071004);
@@ -747,19 +747,19 @@ implementation
       end;
 
 
-    procedure tcg.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const paraloc : TCGPara);
+    procedure tcg.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : TCGPara);
       var
          ref : treference;
       begin
-         paraloc.check_simple_location;
-         case paraloc.location^.loc of
+         cgpara.check_simple_location;
+         case cgpara.location^.loc of
             LOC_REGISTER,LOC_CREGISTER:
-              a_load_ref_reg(list,size,paraloc.location^.size,r,paraloc.location^.register);
+              a_load_ref_reg(list,size,cgpara.location^.size,r,cgpara.location^.register);
             LOC_REFERENCE,LOC_CREFERENCE:
               begin
                  reference_reset(ref);
-                 ref.base:=paraloc.location^.reference.index;
-                 ref.offset:=paraloc.location^.reference.offset;
+                 ref.base:=cgpara.location^.reference.index;
+                 ref.offset:=cgpara.location^.reference.offset;
                  { use concatcopy, because it can also be a float which fails when
                    load_ref_ref is used }
                  g_concatcopy(list,r,ref,tcgsize2size[size]);
@@ -770,41 +770,42 @@ implementation
       end;
 
 
-    procedure tcg.a_param_loc(list : taasmoutput;const l:tlocation;const paraloc : TCGPara);
+    procedure tcg.a_param_loc(list : taasmoutput;const l:tlocation;const cgpara : TCGPara);
       begin
         case l.loc of
           LOC_REGISTER,
           LOC_CREGISTER :
-            a_param_reg(list,l.size,l.register,paraloc);
+            a_param_reg(list,l.size,l.register,cgpara);
           LOC_CONSTANT :
-            a_param_const(list,l.size,l.value,paraloc);
+            a_param_const(list,l.size,l.value,cgpara);
           LOC_CREFERENCE,
           LOC_REFERENCE :
-            a_param_ref(list,l.size,l.reference,paraloc);
+            a_param_ref(list,l.size,l.reference,cgpara);
           else
             internalerror(2002032211);
         end;
       end;
 
 
-    procedure tcg.a_paramaddr_ref(list : taasmoutput;const r : treference;const paraloc : TCGPara);
+    procedure tcg.a_paramaddr_ref(list : taasmoutput;const r : treference;const cgpara : TCGPara);
       var
          hr : tregister;
       begin
+         cgpara.check_simple_location;
          hr:=getaddressregister(list);
          a_loadaddr_ref_reg(list,r,hr);
-         a_param_reg(list,OS_ADDR,hr,paraloc);
+         a_param_reg(list,OS_ADDR,hr,cgpara);
       end;
 
 
-    procedure tcg.a_param_copy_ref(list : taasmoutput;size : aint;const r : treference;const paraloc : TCGPara);
+    procedure tcg.a_param_copy_ref(list : taasmoutput;size : aint;const r : treference;const cgpara : TCGPara);
       var
         ref : treference;
       begin
-         paraloc.check_simple_location;
-         if not(paraloc.location^.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
+         cgpara.check_simple_location;
+         if not(cgpara.location^.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
            internalerror(2003010901);
-         reference_reset_base(ref,paraloc.location^.reference.index,paraloc.location^.reference.offset);
+         reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
          g_concatcopy(list,r,ref,size);
       end;
 
@@ -972,17 +973,17 @@ implementation
       end;
 
 
-    procedure tcg.a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const paraloc : TCGPara);
+    procedure tcg.a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const cgpara : TCGPara);
       var
          ref : treference;
       begin
-         paraloc.check_simple_location;
-         case paraloc.location^.loc of
+         cgpara.check_simple_location;
+         case cgpara.location^.loc of
             LOC_FPUREGISTER,LOC_CFPUREGISTER:
-              a_loadfpu_reg_reg(list,size,r,paraloc.location^.register);
+              a_loadfpu_reg_reg(list,size,r,cgpara.location^.register);
             LOC_REFERENCE,LOC_CREFERENCE:
               begin
-                 reference_reset_base(ref,paraloc.location^.reference.index,paraloc.location^.reference.offset);
+                 reference_reset_base(ref,cgpara.location^.reference.index,cgpara.location^.reference.offset);
                  a_loadfpu_reg_ref(list,size,r,ref);
               end
             else
@@ -991,17 +992,17 @@ implementation
       end;
 
 
-    procedure tcg.a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const paraloc : TCGPara);
+    procedure tcg.a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const cgpara : TCGPara);
       var
          href : treference;
       begin
-         paraloc.check_simple_location;
-         case paraloc.location^.loc of
+         cgpara.check_simple_location;
+         case cgpara.location^.loc of
           LOC_FPUREGISTER,LOC_CFPUREGISTER:
-            a_loadfpu_ref_reg(list,size,ref,paraloc.location^.register);
+            a_loadfpu_ref_reg(list,size,ref,cgpara.location^.register);
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
-              reference_reset_base(href,paraloc.location^.reference.index,paraloc.location^.reference.offset);
+              reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset);
               { concatcopy should choose the best way to copy the data }
               g_concatcopy(list,ref,href,tcgsize2size[size]);
             end
@@ -1255,18 +1256,18 @@ implementation
       end;
 
 
-    procedure tcg.a_parammm_reg(list: taasmoutput; size: tcgsize; reg: tregister;const paraloc : TCGPara;shuffle : pmmshuffle);
+    procedure tcg.a_parammm_reg(list: taasmoutput; size: tcgsize; reg: tregister;const cgpara : TCGPara;shuffle : pmmshuffle);
       var
         href : treference;
       begin
-         paraloc.check_simple_location;
-         case paraloc.location^.loc of
+         cgpara.check_simple_location;
+         case cgpara.location^.loc of
           LOC_MMREGISTER,LOC_CMMREGISTER:
-            a_loadmm_reg_reg(list,size,paraloc.location^.size,reg,paraloc.location^.register,shuffle);
+            a_loadmm_reg_reg(list,size,cgpara.location^.size,reg,cgpara.location^.register,shuffle);
           LOC_REFERENCE,LOC_CREFERENCE:
             begin
-              reference_reset_base(href,paraloc.location^.reference.index,paraloc.location^.reference.offset);
-              a_loadmm_reg_ref(list,size,paraloc.location^.size,reg,href,shuffle);
+              reference_reset_base(href,cgpara.location^.reference.index,cgpara.location^.reference.offset);
+              a_loadmm_reg_ref(list,size,cgpara.location^.size,reg,href,shuffle);
             end
           else
             internalerror(200310123);
@@ -1274,32 +1275,32 @@ implementation
       end;
 
 
-    procedure tcg.a_parammm_ref(list: taasmoutput; size: tcgsize;const ref: treference;const paraloc : TCGPara;shuffle : pmmshuffle);
+    procedure tcg.a_parammm_ref(list: taasmoutput; size: tcgsize;const ref: treference;const cgpara : TCGPara;shuffle : pmmshuffle);
       var
          hr : tregister;
          hs : tmmshuffle;
       begin
-         paraloc.check_simple_location;
-         hr:=getmmregister(list,paraloc.location^.size);
-         a_loadmm_ref_reg(list,size,paraloc.location^.size,ref,hr,shuffle);
+         cgpara.check_simple_location;
+         hr:=getmmregister(list,cgpara.location^.size);
+         a_loadmm_ref_reg(list,size,cgpara.location^.size,ref,hr,shuffle);
          if realshuffle(shuffle) then
            begin
              hs:=shuffle^;
              removeshuffles(hs);
-             a_parammm_reg(list,paraloc.location^.size,hr,paraloc,@hs);
+             a_parammm_reg(list,cgpara.location^.size,hr,cgpara,@hs);
            end
          else
-           a_parammm_reg(list,paraloc.location^.size,hr,paraloc,shuffle);
+           a_parammm_reg(list,cgpara.location^.size,hr,cgpara,shuffle);
       end;
 
 
-    procedure tcg.a_parammm_loc(list: taasmoutput;const loc: tlocation; const paraloc : TCGPara;shuffle : pmmshuffle);
+    procedure tcg.a_parammm_loc(list: taasmoutput;const loc: tlocation; const cgpara : TCGPara;shuffle : pmmshuffle);
       begin
         case loc.loc of
           LOC_MMREGISTER,LOC_CMMREGISTER:
-            a_parammm_reg(list,loc.size,loc.register,paraloc,shuffle);
+            a_parammm_reg(list,loc.size,loc.register,cgpara,shuffle);
           LOC_REFERENCE,LOC_CREFERENCE:
-            a_parammm_ref(list,loc.size,loc.reference,paraloc,shuffle);
+            a_parammm_ref(list,loc.size,loc.reference,cgpara,shuffle);
           else
             internalerror(200310123);
         end;
@@ -1367,31 +1368,31 @@ implementation
 
     procedure tcg.g_copyshortstring(list : taasmoutput;const source,dest : treference;len:byte);
       var
-        paraloc1,paraloc2,paraloc3 : TCGPara;
-      begin
-        paraloc1.init;
-        paraloc2.init;
-        paraloc3.init;
-        paramanager.getintparaloc(pocall_default,1,paraloc1);
-        paramanager.getintparaloc(pocall_default,2,paraloc2);
-        paramanager.getintparaloc(pocall_default,3,paraloc3);
-        paramanager.allocparaloc(list,paraloc3);
-        a_paramaddr_ref(list,dest,paraloc3);
-        paramanager.allocparaloc(list,paraloc2);
-        a_paramaddr_ref(list,source,paraloc2);
-        paramanager.allocparaloc(list,paraloc1);
-        a_param_const(list,OS_INT,len,paraloc1);
-        paramanager.freeparaloc(list,paraloc3);
-        paramanager.freeparaloc(list,paraloc2);
-        paramanager.freeparaloc(list,paraloc1);
+        cgpara1,cgpara2,cgpara3 : TCGPara;
+      begin
+        cgpara1.init;
+        cgpara2.init;
+        cgpara3.init;
+        paramanager.getintparaloc(pocall_default,1,cgpara1);
+        paramanager.getintparaloc(pocall_default,2,cgpara2);
+        paramanager.getintparaloc(pocall_default,3,cgpara3);
+        paramanager.allocparaloc(list,cgpara3);
+        a_paramaddr_ref(list,dest,cgpara3);
+        paramanager.allocparaloc(list,cgpara2);
+        a_paramaddr_ref(list,source,cgpara2);
+        paramanager.allocparaloc(list,cgpara1);
+        a_param_const(list,OS_INT,len,cgpara1);
+        paramanager.freeparaloc(list,cgpara3);
+        paramanager.freeparaloc(list,cgpara2);
+        paramanager.freeparaloc(list,cgpara1);
         alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
         alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
         a_call_name(list,'FPC_SHORTSTR_ASSIGN');
         dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
         dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
-        paraloc3.done;
-        paraloc2.done;
-        paraloc1.done;
+        cgpara3.done;
+        cgpara2.done;
+        cgpara1.done;
       end;
 
 
@@ -1399,12 +1400,12 @@ implementation
       var
         href : treference;
         incrfunc : string;
-        paraloc1,paraloc2 : TCGPara;
+        cgpara1,cgpara2 : TCGPara;
       begin
-         paraloc1.init;
-         paraloc2.init;
-         paramanager.getintparaloc(pocall_default,1,paraloc1);
-         paramanager.getintparaloc(pocall_default,2,paraloc2);
+         cgpara1.init;
+         cgpara2.init;
+         paramanager.getintparaloc(pocall_default,1,cgpara1);
+         paramanager.getintparaloc(pocall_default,2,cgpara2);
          if is_interfacecom(t) then
           incrfunc:='FPC_INTF_INCR_REF'
          else if is_ansistring(t) then
@@ -1431,10 +1432,10 @@ implementation
          { call the special incr function or the generic addref }
          if incrfunc<>'' then
           begin
-            paramanager.allocparaloc(list,paraloc1);
+            paramanager.allocparaloc(list,cgpara1);
             { these functions get the pointer by value }
-            a_param_ref(list,OS_ADDR,ref,paraloc1);
-            paramanager.freeparaloc(list,paraloc1);
+            a_param_ref(list,OS_ADDR,ref,cgpara1);
+            paramanager.freeparaloc(list,cgpara1);
             alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
             a_call_name(list,incrfunc);
             dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
@@ -1442,18 +1443,18 @@ implementation
          else
           begin
             reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
-            paramanager.allocparaloc(list,paraloc2);
-            a_paramaddr_ref(list,href,paraloc2);
-            paramanager.allocparaloc(list,paraloc1);
-            a_paramaddr_ref(list,ref,paraloc1);
-            paramanager.freeparaloc(list,paraloc1);
-            paramanager.freeparaloc(list,paraloc2);
+            paramanager.allocparaloc(list,cgpara2);
+            a_paramaddr_ref(list,href,cgpara2);
+            paramanager.allocparaloc(list,cgpara1);
+            a_paramaddr_ref(list,ref,cgpara1);
+            paramanager.freeparaloc(list,cgpara1);
+            paramanager.freeparaloc(list,cgpara2);
             alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
             a_call_name(list,'FPC_ADDREF');
             dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
           end;
-         paraloc2.done;
-         paraloc1.done;
+         cgpara2.done;
+         cgpara1.done;
       end;
 
 
@@ -1462,12 +1463,12 @@ implementation
         href : treference;
         decrfunc : string;
         needrtti : boolean;
-        paraloc1,paraloc2 : TCGPara;
+        cgpara1,cgpara2 : TCGPara;
       begin
-        paraloc1.init;
-        paraloc2.init;
-        paramanager.getintparaloc(pocall_default,1,paraloc1);
-        paramanager.getintparaloc(pocall_default,2,paraloc2);
+        cgpara1.init;
+        cgpara2.init;
+        paramanager.getintparaloc(pocall_default,1,cgpara1);
+        paramanager.getintparaloc(pocall_default,2,cgpara2);
         needrtti:=false;
         if is_interfacecom(t) then
           decrfunc:='FPC_INTF_DECR_REF'
@@ -1501,14 +1502,14 @@ implementation
             if needrtti then
              begin
                reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
-               paramanager.allocparaloc(list,paraloc2);
-               a_paramaddr_ref(list,href,paraloc2);
+               paramanager.allocparaloc(list,cgpara2);
+               a_paramaddr_ref(list,href,cgpara2);
              end;
-            paramanager.allocparaloc(list,paraloc1);
-            a_paramaddr_ref(list,ref,paraloc1);
-            paramanager.freeparaloc(list,paraloc1);
+            paramanager.allocparaloc(list,cgpara1);
+            a_paramaddr_ref(list,ref,cgpara1);
+            paramanager.freeparaloc(list,cgpara1);
             if needrtti then
-              paramanager.freeparaloc(list,paraloc2);
+              paramanager.freeparaloc(list,cgpara2);
             alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
             a_call_name(list,decrfunc);
             dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
@@ -1516,12 +1517,12 @@ implementation
          else
           begin
             reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
-            paramanager.allocparaloc(list,paraloc2);
-            a_paramaddr_ref(list,href,paraloc2);
-            paramanager.allocparaloc(list,paraloc1);
-            a_paramaddr_ref(list,ref,paraloc1);
-            paramanager.freeparaloc(list,paraloc1);
-            paramanager.freeparaloc(list,paraloc2);
+            paramanager.allocparaloc(list,cgpara2);
+            a_paramaddr_ref(list,href,cgpara2);
+            paramanager.allocparaloc(list,cgpara1);
+            a_paramaddr_ref(list,ref,cgpara1);
+            paramanager.freeparaloc(list,cgpara1);
+            paramanager.freeparaloc(list,cgpara2);
             alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
             a_call_name(list,'FPC_DECREF');
             dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
@@ -1529,20 +1530,20 @@ implementation
         { Temp locations need always to be reset to 0 }
         if tg.istemp(ref) then
           a_load_const_ref(list,OS_ADDR,0,ref);
-        paraloc2.done;
-        paraloc1.done;
+        cgpara2.done;
+        cgpara1.done;
       end;
 
 
     procedure tcg.g_initialize(list : taasmoutput;t : tdef;const ref : treference);
       var
          href : treference;
-         paraloc1,paraloc2 : TCGPara;
+         cgpara1,cgpara2 : TCGPara;
       begin
-        paraloc1.init;
-        paraloc2.init;
-        paramanager.getintparaloc(pocall_default,1,paraloc1);
-        paramanager.getintparaloc(pocall_default,2,paraloc2);
+        cgpara1.init;
+        cgpara2.init;
+        paramanager.getintparaloc(pocall_default,1,cgpara1);
+        paramanager.getintparaloc(pocall_default,2,cgpara2);
          if is_ansistring(t) or
             is_widestring(t) or
             is_interfacecom(t) or
@@ -1551,32 +1552,32 @@ implementation
          else
            begin
               reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
-              paramanager.allocparaloc(list,paraloc2);
-              a_paramaddr_ref(list,href,paraloc2);
-              paramanager.allocparaloc(list,paraloc1);
-              a_paramaddr_ref(list,ref,paraloc1);
-              paramanager.freeparaloc(list,paraloc1);
-              paramanager.freeparaloc(list,paraloc2);
+              paramanager.allocparaloc(list,cgpara2);
+              a_paramaddr_ref(list,href,cgpara2);
+              paramanager.allocparaloc(list,cgpara1);
+              a_paramaddr_ref(list,ref,cgpara1);
+              paramanager.freeparaloc(list,cgpara1);
+              paramanager.freeparaloc(list,cgpara2);
               alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
               alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
               a_call_name(list,'FPC_INITIALIZE');
               dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
               dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
            end;
-        paraloc1.done;
-        paraloc2.done;
+        cgpara1.done;
+        cgpara2.done;
       end;
 
 
     procedure tcg.g_finalize(list : taasmoutput;t : tdef;const ref : treference);
       var
          href : treference;
-         paraloc1,paraloc2 : TCGPara;
+         cgpara1,cgpara2 : TCGPara;
       begin
-        paraloc1.init;
-        paraloc2.init;
-        paramanager.getintparaloc(pocall_default,1,paraloc1);
-        paramanager.getintparaloc(pocall_default,2,paraloc2);
+        cgpara1.init;
+        cgpara2.init;
+        paramanager.getintparaloc(pocall_default,1,cgpara1);
+        paramanager.getintparaloc(pocall_default,2,cgpara2);
          if is_ansistring(t) or
             is_widestring(t) or
             is_interfacecom(t) then
@@ -1589,20 +1590,20 @@ implementation
          else
            begin
               reference_reset_symbol(href,tstoreddef(t).get_rtti_label(initrtti),0);
-              paramanager.allocparaloc(list,paraloc2);
-              a_paramaddr_ref(list,href,paraloc2);
-              paramanager.allocparaloc(list,paraloc1);
-              a_paramaddr_ref(list,ref,paraloc1);
-              paramanager.freeparaloc(list,paraloc1);
-              paramanager.freeparaloc(list,paraloc2);
+              paramanager.allocparaloc(list,cgpara2);
+              a_paramaddr_ref(list,href,cgpara2);
+              paramanager.allocparaloc(list,cgpara1);
+              a_paramaddr_ref(list,ref,cgpara1);
+              paramanager.freeparaloc(list,cgpara1);
+              paramanager.freeparaloc(list,cgpara2);
               alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
               alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
               a_call_name(list,'FPC_FINALIZE');
               dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
               dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
            end;
-        paraloc1.done;
-        paraloc2.done;
+        cgpara1.done;
+        cgpara2.done;
       end;
 
 
@@ -1772,21 +1773,21 @@ implementation
     procedure tcg.g_maybe_testself(list : taasmoutput;reg:tregister);
       var
         OKLabel : tasmlabel;
-        paraloc1 : TCGPara;
+        cgpara1 : TCGPara;
       begin
         if (cs_check_object in aktlocalswitches) or
            (cs_check_range in aktlocalswitches) then
          begin
            objectlibrary.getlabel(oklabel);
            a_cmp_const_reg_label(list,OS_ADDR,OC_NE,0,reg,oklabel);
-           paraloc1.init;
-           paramanager.getintparaloc(pocall_default,1,paraloc1);
-           paramanager.allocparaloc(list,paraloc1);
-           a_param_const(list,OS_INT,210,paraloc1);
-           paramanager.freeparaloc(list,paraloc1);
+           cgpara1.init;
+           paramanager.getintparaloc(pocall_default,1,cgpara1);
+           paramanager.allocparaloc(list,cgpara1);
+           a_param_const(list,OS_INT,210,cgpara1);
+           paramanager.freeparaloc(list,cgpara1);
            a_call_name(list,'FPC_HANDLEERROR');
            a_label(list,oklabel);
-           paraloc1.done;
+           cgpara1.done;
          end;
       end;
 
@@ -1794,21 +1795,21 @@ implementation
     procedure tcg.g_maybe_testvmt(list : taasmoutput;reg:tregister;objdef:tobjectdef);
       var
         hrefvmt : treference;
-        paraloc1,paraloc2 : TCGPara;
+        cgpara1,cgpara2 : TCGPara;
       begin
-        paraloc1.init;
-        paraloc2.init;
-        paramanager.getintparaloc(pocall_default,1,paraloc1);
-        paramanager.getintparaloc(pocall_default,2,paraloc2);
+        cgpara1.init;
+        cgpara2.init;
+        paramanager.getintparaloc(pocall_default,1,cgpara1);
+        paramanager.getintparaloc(pocall_default,2,cgpara2);
         if (cs_check_object in aktlocalswitches) then
          begin
            reference_reset_symbol(hrefvmt,objectlibrary.newasmsymbol(objdef.vmt_mangledname,AB_EXTERNAL,AT_DATA),0);
-           paramanager.allocparaloc(list,paraloc2);
-           a_paramaddr_ref(list,hrefvmt,paraloc2);
-           paramanager.allocparaloc(list,paraloc1);
-           a_param_reg(list,OS_ADDR,reg,paraloc1);
-           paramanager.freeparaloc(list,paraloc1);
-           paramanager.freeparaloc(list,paraloc2);
+           paramanager.allocparaloc(list,cgpara2);
+           a_paramaddr_ref(list,hrefvmt,cgpara2);
+           paramanager.allocparaloc(list,cgpara1);
+           a_param_reg(list,OS_ADDR,reg,cgpara1);
+           paramanager.freeparaloc(list,cgpara1);
+           paramanager.freeparaloc(list,cgpara2);
            alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
            a_call_name(list,'FPC_CHECK_OBJECT_EXT');
            dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
@@ -1816,15 +1817,15 @@ implementation
         else
          if (cs_check_range in aktlocalswitches) then
           begin
-            paramanager.allocparaloc(list,paraloc1);
-            a_param_reg(list,OS_ADDR,reg,paraloc1);
-            paramanager.freeparaloc(list,paraloc1);
+            paramanager.allocparaloc(list,cgpara1);
+            a_param_reg(list,OS_ADDR,reg,cgpara1);
+            paramanager.freeparaloc(list,cgpara1);
             alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
             a_call_name(list,'FPC_CHECK_OBJECT');
             dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
           end;
-        paraloc1.done;
-        paraloc2.done;
+        cgpara1.done;
+        cgpara2.done;
       end;
 
 
@@ -1835,7 +1836,7 @@ implementation
     procedure tcg.g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);
       var
         sizereg,sourcereg,lenreg : tregister;
-        paraloc1,paraloc2,paraloc3 : TCGPara;
+        cgpara1,cgpara2,cgpara3 : TCGPara;
       begin
         { because some abis don't support dynamic stack allocation properly
           open array value parameters are copied onto the heap
@@ -1860,67 +1861,67 @@ implementation
         a_loadaddr_ref_reg(list,ref,sourcereg);
 
         { do getmem call }
-        paraloc1.init;
-        paramanager.getintparaloc(pocall_default,1,paraloc1);
-        paramanager.allocparaloc(list,paraloc1);
-        a_param_reg(list,OS_INT,sizereg,paraloc1);
-        paramanager.freeparaloc(list,paraloc1);
+        cgpara1.init;
+        paramanager.getintparaloc(pocall_default,1,cgpara1);
+        paramanager.allocparaloc(list,cgpara1);
+        a_param_reg(list,OS_INT,sizereg,cgpara1);
+        paramanager.freeparaloc(list,cgpara1);
         alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
         alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
         a_call_name(list,'FPC_GETMEM');
         dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
         dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
-        paraloc1.done;
+        cgpara1.done;
         { return the new address }
         a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,destreg);
 
         { do move call }
-        paraloc1.init;
-        paraloc2.init;
-        paraloc3.init;
-        paramanager.getintparaloc(pocall_default,1,paraloc1);
-        paramanager.getintparaloc(pocall_default,2,paraloc2);
-        paramanager.getintparaloc(pocall_default,3,paraloc3);
+        cgpara1.init;
+        cgpara2.init;
+        cgpara3.init;
+        paramanager.getintparaloc(pocall_default,1,cgpara1);
+        paramanager.getintparaloc(pocall_default,2,cgpara2);
+        paramanager.getintparaloc(pocall_default,3,cgpara3);
         { load size }
-        paramanager.allocparaloc(list,paraloc3);
-        a_param_reg(list,OS_INT,sizereg,paraloc3);
+        paramanager.allocparaloc(list,cgpara3);
+        a_param_reg(list,OS_INT,sizereg,cgpara3);
         { load destination }
-        paramanager.allocparaloc(list,paraloc2);
-        a_param_reg(list,OS_ADDR,destreg,paraloc2);
+        paramanager.allocparaloc(list,cgpara2);
+        a_param_reg(list,OS_ADDR,destreg,cgpara2);
         { load source }
-        paramanager.allocparaloc(list,paraloc1);
-        a_param_reg(list,OS_ADDR,sourcereg,paraloc1);
-        paramanager.freeparaloc(list,paraloc3);
-        paramanager.freeparaloc(list,paraloc2);
-        paramanager.freeparaloc(list,paraloc1);
+        paramanager.allocparaloc(list,cgpara1);
+        a_param_reg(list,OS_ADDR,sourcereg,cgpara1);
+        paramanager.freeparaloc(list,cgpara3);
+        paramanager.freeparaloc(list,cgpara2);
+        paramanager.freeparaloc(list,cgpara1);
         alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
         alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
         a_call_name(list,'FPC_MOVE');
         dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
         dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
-        paraloc3.done;
-        paraloc2.done;
-        paraloc1.done;
+        cgpara3.done;
+        cgpara2.done;
+        cgpara1.done;
       end;
 
 
     procedure tcg.g_releasevaluepara_openarray(list : taasmoutput;const l:tlocation);
       var
-        paraloc1 : TCGPara;
+        cgpara1 : TCGPara;
       begin
         { do move call }
-        paraloc1.init;
-        paramanager.getintparaloc(pocall_default,1,paraloc1);
+        cgpara1.init;
+        paramanager.getintparaloc(pocall_default,1,cgpara1);
         { load source }
-        paramanager.allocparaloc(list,paraloc1);
-        a_param_loc(list,l,paraloc1);
-        paramanager.freeparaloc(list,paraloc1);
+        paramanager.allocparaloc(list,cgpara1);
+        a_param_loc(list,l,cgpara1);
+        paramanager.freeparaloc(list,cgpara1);
         alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
         alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
         a_call_name(list,'FPC_FREEMEM');
         dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
         dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
-        paraloc1.done;
+        cgpara1.done;
       end;
 
 
@@ -2047,7 +2048,11 @@ finalization
 end.
 {
   $Log$
-  Revision 1.187  2004-11-30 18:13:39  jonas
+  Revision 1.188  2005-01-18 22:19:20  peter
+    * multiple location support for i386 a_param_ref
+    * remove a_param_copy_ref for i386
+
+  Revision 1.187  2004/11/30 18:13:39  jonas
     * patch from Peter to fix inlining of case statements
 
   Revision 1.186  2004/11/08 21:47:39  florian
@@ -2113,7 +2118,7 @@ end.
     * removed location-release/reference_release
 
   Revision 1.169  2004/09/21 17:25:12  peter
-    * paraloc branch merged
+    * cgpara branch merged
 
   Revision 1.168.4.4  2004/09/20 20:45:57  peter
     * remove cg64.a_reg_alloc, it should not be used since it
@@ -2127,7 +2132,7 @@ end.
     * fixed alignment issues
 
   Revision 1.168.4.1  2004/08/31 20:43:06  peter
-    * paraloc patch
+    * cgpara patch
 
   Revision 1.168  2004/07/09 23:41:04  jonas
     * support register parameters for inlined procedures + some inline

+ 119 - 71
compiler/i386/cgcpu.pas

@@ -30,8 +30,8 @@ unit cgcpu;
        globtype,
        cgbase,cgobj,cg64f32,cgx86,
        aasmbase,aasmtai,aasmcpu,
-       cpubase,cpuinfo,parabase,cgutils,
-       node,symconst
+       cpubase,parabase,cgutils,
+       symconst
        ;
 
     type
@@ -65,7 +65,15 @@ unit cgcpu;
     uses
        globals,verbose,systems,cutils,
        paramgr,procinfo,
-       rgcpu,rgx86,tgobj;
+       rgcpu,rgx86;
+
+    function use_push(const cgpara:tcgpara):boolean;
+      begin
+        result:=assigned(cgpara.location) and
+                (cgpara.location^.loc=LOC_REFERENCE) and
+                (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
+      end;
+
 
     procedure Tcg386.init_register_allocators;
       begin
@@ -85,16 +93,14 @@ unit cgcpu;
         pushsize : tcgsize;
       begin
         check_register_size(size,r);
-        with cgpara do
-          if assigned(location) and
-             (location^.loc=LOC_REFERENCE) and
-             (location^.reference.index=NR_STACK_POINTER_REG) then
-            begin
-              pushsize:=int_cgsize(alignment);
-              list.concat(taicpu.op_reg(A_PUSH,tcgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
-            end
-          else
-            inherited a_param_reg(list,size,r,cgpara);
+        if use_push(cgpara) then
+          begin
+            cgpara.check_simple_location;
+            pushsize:=int_cgsize(cgpara.alignment);
+            list.concat(taicpu.op_reg(A_PUSH,tcgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
+          end
+        else
+          inherited a_param_reg(list,size,r,cgpara);
       end;
 
 
@@ -102,41 +108,81 @@ unit cgcpu;
       var
         pushsize : tcgsize;
       begin
-        with cgpara do
-          if assigned(location) and
-             (location^.loc=LOC_REFERENCE) and
-             (location^.reference.index=NR_STACK_POINTER_REG) then
-            begin
-              pushsize:=int_cgsize(alignment);
-              list.concat(taicpu.op_const(A_PUSH,tcgsize2opsize[pushsize],a));
-            end
-          else
-            inherited a_param_const(list,size,a,cgpara);
+        if use_push(cgpara) then
+          begin
+            cgpara.check_simple_location;
+            pushsize:=int_cgsize(cgpara.alignment);
+            list.concat(taicpu.op_const(A_PUSH,tcgsize2opsize[pushsize],a));
+          end
+        else
+          inherited a_param_const(list,size,a,cgpara);
       end;
 
 
     procedure tcg386.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : tcgpara);
-      var
-        pushsize : tcgsize;
-        tmpreg : tregister;
-      begin
-        with cgpara do
-          if assigned(location) and
-             (location^.loc=LOC_REFERENCE) and
-             (location^.reference.index=NR_STACK_POINTER_REG) then
+
+        procedure pushdata(paraloc:pcgparalocation;ofs:aint);
+        var
+          pushsize : tcgsize;
+          tmpreg   : tregister;
+          href     : treference;
+        begin
+          if not assigned(paraloc) then
+            exit;
+          if (paraloc^.loc<>LOC_REFERENCE) or
+             (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
+             (tcgsize2size[paraloc^.size]>sizeof(aint)) then
+            internalerror(200501162);
+          { Pushes are needed in reverse order, add the size of the
+            current location to the offset where to load from. This
+            prevents wrong calculations for the last location when
+            the size is not a power of 2 }
+          if assigned(paraloc^.next) then
+            pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
+          { Push the data starting at ofs }
+          href:=r;
+          inc(href.offset,ofs);
+          if tcgsize2size[paraloc^.size]>cgpara.alignment then
+            pushsize:=paraloc^.size
+          else
+            pushsize:=int_cgsize(cgpara.alignment);
+          if tcgsize2size[paraloc^.size]<cgpara.alignment then
             begin
-              pushsize:=int_cgsize(alignment);
-              if tcgsize2size[size]<alignment then
-                begin
-                  tmpreg:=getintregister(list,pushsize);
-                  a_load_ref_reg(list,size,pushsize,r,tmpreg);
-                  list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],tmpreg));
-                end
-              else
-                list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[pushsize],r));
+              tmpreg:=getintregister(list,pushsize);
+              a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
+              list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],tmpreg));
             end
           else
-            inherited a_param_ref(list,size,r,cgpara);
+            list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[pushsize],href));
+        end;
+
+      var
+        len : aint;
+        href : treference;
+      begin
+        { cgpara.size=OS_NO requires a copy on the stack }
+        if use_push(cgpara) then
+          begin
+            if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
+              internalerror(200501161);
+            { Record copy? }
+            if (cgpara.size=OS_NO) then
+              begin
+                cgpara.check_simple_location;
+                len:=align(cgpara.intsize,cgpara.alignment);
+                g_stackpointer_alloc(list,len);
+                reference_reset_base(href,NR_STACK_POINTER_REG,0);
+                g_concatcopy(list,r,href,len);
+              end
+            else
+              begin
+                { We need to push the data in reverse order,
+                  therefor we use a recursive algorithm }
+                pushdata(cgpara.location,0);
+              end
+          end
+        else
+          inherited a_param_ref(list,size,r,cgpara);
       end;
 
 
@@ -149,35 +195,33 @@ unit cgcpu;
           begin
             if (segment<>NR_NO) then
               cgmessage(cg_e_cant_use_far_pointer_there);
-            with cgpara do
-              if assigned(location) and
-                 (location^.loc=LOC_REFERENCE) and
-                 (location^.reference.index=NR_STACK_POINTER_REG) then
-                begin
-                  opsize:=tcgsize2opsize[OS_ADDR];
-                  if (base=NR_NO) and (index=NR_NO) then
-                    begin
-                      if assigned(symbol) then
-                        list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
-                      else
-                        list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
-                    end
-                  else if (base=NR_NO) and (index<>NR_NO) and
-                          (offset=0) and (scalefactor=0) and (symbol=nil) then
-                    list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
-                  else if (base<>NR_NO) and (index=NR_NO) and
-                          (offset=0) and (symbol=nil) then
-                    list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
-                  else
-                    begin
-                      tmpreg:=getaddressregister(list);
-                      a_loadaddr_ref_reg(list,r,tmpreg);
-                      list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
-                    end;
-                end
-              else
-                inherited a_paramaddr_ref(list,r,cgpara);
-        end;
+            if use_push(cgpara) then
+              begin
+                cgpara.check_simple_location;
+                opsize:=tcgsize2opsize[OS_ADDR];
+                if (base=NR_NO) and (index=NR_NO) then
+                  begin
+                    if assigned(symbol) then
+                      list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
+                    else
+                      list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
+                  end
+                else if (base=NR_NO) and (index<>NR_NO) and
+                        (offset=0) and (scalefactor=0) and (symbol=nil) then
+                  list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
+                else if (base<>NR_NO) and (index=NR_NO) and
+                        (offset=0) and (symbol=nil) then
+                  list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
+                else
+                  begin
+                    tmpreg:=getaddressregister(list);
+                    a_loadaddr_ref_reg(list,r,tmpreg);
+                    list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
+                  end;
+              end
+            else
+              inherited a_paramaddr_ref(list,r,cgpara);
+          end;
       end;
 
 
@@ -520,7 +564,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.62  2004-11-21 17:54:59  peter
+  Revision 1.63  2005-01-18 22:19:20  peter
+    * multiple location support for i386 a_param_ref
+    * remove a_param_copy_ref for i386
+
+  Revision 1.62  2004/11/21 17:54:59  peter
     * ttempcreatenode.create_reg merged into .create with parameter
       whether a register is allowed
     * funcret_paraloc renamed to funcretloc

+ 126 - 49
compiler/i386/cpupara.pas

@@ -27,13 +27,14 @@ unit cpupara;
   interface
 
     uses
-       cclasses,globtype,
+       globtype,
        aasmtai,cpubase,cgbase,
        symconst,symtype,symsym,symdef,
        parabase,paramgr;
 
     type
        ti386paramanager = class(tparamanager)
+          function param_use_paraloc(const cgpara:tcgpara):boolean;override;
           function ret_in_param(def : tdef;calloption : tproccalloption) : boolean;override;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
           function get_para_align(calloption : tproccalloption):byte;override;
@@ -55,6 +56,7 @@ unit cpupara;
           procedure create_register_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parareg,parasize:longint);
        end;
 
+
   implementation
 
     uses
@@ -70,6 +72,24 @@ unit cpupara;
                                 TI386PARAMANAGER
 ****************************************************************************}
 
+    function ti386paramanager.param_use_paraloc(const cgpara:tcgpara):boolean;
+      var
+        paraloc : pcgparalocation;
+      begin
+        if not assigned(cgpara.location) then
+          internalerror(200410102);
+        result:=true;
+        { All locations are LOC_REFERENCE }
+        paraloc:=cgpara.location;
+        while assigned(paraloc) do
+          begin
+            if (paraloc^.loc<>LOC_REFERENCE) then
+              result:=false;
+            paraloc:=paraloc^.next;
+          end;
+      end;
+
+
     function ti386paramanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
       begin
         case target_info.system of
@@ -120,7 +140,7 @@ unit cpupara;
                        (varspez=vs_value) and
                        (tarraydef(def).highrange>=tarraydef(def).lowrange) then
                      begin
-                       result:=true;
+                       result:=false;
                        exit;
                      end;
                   end;
@@ -291,8 +311,10 @@ unit cpupara;
         hp : tparavarsym;
         paraloc : pcgparalocation;
         l,
-        varalign,
-        paraalign : longint;
+        paralen,
+        varalign   : longint;
+        paraalign  : shortint;
+        pushaddr   : boolean;
         paracgsize : tcgsize;
       begin
         paraalign:=get_para_align(p.proccalloption);
@@ -313,32 +335,59 @@ unit cpupara;
         for i:=0 to paras.count-1 do
           begin
             hp:=tparavarsym(paras[i]);
-            if push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption) then
+            pushaddr:=push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption);
+            if pushaddr then
               begin
+                paralen:=sizeof(aint);
                 paracgsize:=OS_ADDR;
-                hp.paraloc[side].intsize:=tcgsize2size[OS_ADDR];
               end
             else
               begin
-                paracgsize:=def_cgSize(hp.vartype.def);
-                if paracgsize=OS_NO then
-                  paracgsize:=OS_ADDR;
-                hp.paraloc[side].intsize := tcgsize2size[paracgsize];
+                paralen:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
+                paracgsize:=def_cgsize(hp.vartype.def);
               end;
             hp.paraloc[side].reset;
             hp.paraloc[side].size:=paracgsize;
+            hp.paraloc[side].intsize:=paralen;
             hp.paraloc[side].Alignment:=paraalign;
-            paraloc:=hp.paraloc[side].add_location;
-            paraloc^.loc:=LOC_REFERENCE;
-            paraloc^.size:=paracgsize;
-            if side=callerside then
-              paraloc^.reference.index:=NR_STACK_POINTER_REG
+            { Copy to stack? }
+            if paracgsize=OS_NO then
+              begin
+                paraloc:=hp.paraloc[side].add_location;
+                paraloc^.loc:=LOC_REFERENCE;
+                paraloc^.size:=paracgsize;
+                if side=callerside then
+                  paraloc^.reference.index:=NR_STACK_POINTER_REG
+                else
+                  paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+                paraloc^.reference.offset:=parasize;
+                parasize:=align(parasize+paralen,varalign);
+              end
             else
-              paraloc^.reference.index:=NR_FRAME_POINTER_REG;
-            l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
-            varalign:=used_align(size_2_align(l),paraalign,paraalign);
-            paraloc^.reference.offset:=parasize;
-            parasize:=align(parasize+l,varalign);
+              begin
+                if paralen=0 then
+                  internalerror(200501163);
+                while (paralen>0) do
+                  begin
+                    { We can allocate at maximum 32 bits per location }
+                    if paralen>sizeof(aint) then
+                      l:=sizeof(aint)
+                    else
+                      l:=paralen;
+                    paraloc:=hp.paraloc[side].add_location;
+                    paraloc^.loc:=LOC_REFERENCE;
+                    paraloc^.size:=int_cgsize(l);
+                    if side=callerside then
+                      paraloc^.reference.index:=NR_STACK_POINTER_REG
+                    else
+                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                    varalign:=used_align(size_2_align(l),paraalign,paraalign);
+                    paraloc^.reference.offset:=parasize;
+                    parasize:=align(parasize+l,varalign);
+                    dec(paralen,l);
+                  end;
+              end;
           end;
         { Adapt offsets for left-to-right calling }
         if p.proccalloption in pushleftright_pocalls then
@@ -378,13 +427,13 @@ unit cpupara;
       var
         hp : tparavarsym;
         paraloc : pcgparalocation;
-        pushaddr,
-        is_64bit : boolean;
         paracgsize : tcgsize;
         i : integer;
         l,
-        varalign,
-        paraalign : longint;
+        paralen,
+        varalign : longint;
+        pushaddr : boolean;
+        paraalign : shortint;
       begin
         paraalign:=get_para_align(p.proccalloption);
         { Register parameters are assigned from left to right }
@@ -394,21 +443,17 @@ unit cpupara;
             pushaddr:=push_addr_param(hp.varspez,hp.vartype.def,p.proccalloption);
             if pushaddr then
               begin
+                paralen:=sizeof(aint);
                 paracgsize:=OS_ADDR;
-                hp.paraloc[side].intsize:=tcgsize2size[OS_ADDR];
               end
             else
               begin
-                paracgsize:=def_cgSize(hp.vartype.def);
-                hp.paraloc[side].intsize := hp.vartype.def.size;
-                if (hp.paraloc[side].intsize = 0) and
-                   { records can have size 0}
-                   (hp.vartype.def.deftype <> recorddef) then
-                  hp.paraloc[side].intsize := tcgsize2size[OS_ADDR];
+                paralen:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
+                paracgsize:=def_cgsize(hp.vartype.def);
               end;
-            is_64bit:=(paracgsize in [OS_64,OS_S64,OS_F64]);
             hp.paraloc[side].reset;
             hp.paraloc[side].size:=paracgsize;
+            hp.paraloc[side].intsize:=paralen;
             hp.paraloc[side].Alignment:=paraalign;
             {
               EAX
@@ -420,31 +465,59 @@ unit cpupara;
               64bit values,floats,arrays and records are always
               on the stack.
             }
-            paraloc:=hp.paraloc[side].add_location;
-            paraloc^.size:=paracgsize;
             if (parareg<=high(parasupregs)) and
-               not(
-                   is_64bit or
-                   ((hp.vartype.def.deftype in [floatdef,recorddef,arraydef]) and
-                    (not pushaddr))
-                  ) then
+               (paralen<=sizeof(aint)) and
+               (
+                not(hp.vartype.def.deftype in [floatdef,recorddef,arraydef]) or
+                pushaddr
+               ) then
               begin
+                paraloc:=hp.paraloc[side].add_location;
+                paraloc^.size:=paracgsize;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(paracgsize));
                 inc(parareg);
               end
             else
               begin
-                paraloc^.loc:=LOC_REFERENCE;
-                if side=callerside then
-                  paraloc^.reference.index:=NR_STACK_POINTER_REG
+                { Copy to stack? }
+                if paracgsize=OS_NO then
+                  begin
+                    paraloc:=hp.paraloc[side].add_location;
+                    paraloc^.loc:=LOC_REFERENCE;
+                    paraloc^.size:=paracgsize;
+                    if side=callerside then
+                      paraloc^.reference.index:=NR_STACK_POINTER_REG
+                    else
+                      paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                    varalign:=used_align(size_2_align(paralen),paraalign,paraalign);
+                    paraloc^.reference.offset:=parasize;
+                    parasize:=align(parasize+paralen,varalign);
+                  end
                 else
-                  paraloc^.reference.index:=NR_FRAME_POINTER_REG;
-                l:=push_size(hp.varspez,hp.vartype.def,p.proccalloption);
-                varalign:=size_2_align(l);
-                paraloc^.reference.offset:=parasize;
-                varalign:=used_align(varalign,paraalign,paraalign);
-                parasize:=align(parasize+l,varalign);
+                  begin
+                    if paralen=0 then
+                      internalerror(200501163);
+                    while (paralen>0) do
+                      begin
+                        { We can allocate at maximum 32 bits per location }
+                        if paralen>sizeof(aint) then
+                          l:=sizeof(aint)
+                        else
+                          l:=paralen;
+                        paraloc:=hp.paraloc[side].add_location;
+                        paraloc^.loc:=LOC_REFERENCE;
+                        paraloc^.size:=int_cgsize(l);
+                        if side=callerside then
+                          paraloc^.reference.index:=NR_STACK_POINTER_REG
+                        else
+                          paraloc^.reference.index:=NR_FRAME_POINTER_REG;
+                        varalign:=used_align(size_2_align(l),paraalign,paraalign);
+                        paraloc^.reference.offset:=parasize;
+                        parasize:=align(parasize+l,varalign);
+                        dec(paralen,l);
+                      end;
+                  end;
               end;
           end;
         { Register parameters are assigned from left-to-right, adapt offset
@@ -529,7 +602,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.61  2005-01-10 21:50:05  jonas
+  Revision 1.62  2005-01-18 22:19:20  peter
+    * multiple location support for i386 a_param_ref
+    * remove a_param_copy_ref for i386
+
+  Revision 1.61  2005/01/10 21:50:05  jonas
     + support for passing records in registers under darwin
     * tcgpara now also has an intsize field, which contains the size in
       bytes of the whole parameter

+ 10 - 37
compiler/ncgcal.pas

@@ -177,26 +177,7 @@ implementation
                begin
                  size:=align(left.resulttype.def.size,tempcgpara.alignment);
                  if tempcgpara.location^.reference.index=NR_STACK_POINTER_REG then
-                   begin
-                     href:=left.location.reference;
-                     inc(href.offset,size);
-                     while (size>0) do
-                      begin
-                        if (size>=4) or (tempcgpara.alignment>=4) then
-                         begin
-                           cgsize:=OS_32;
-                           dec(href.offset,4);
-                           dec(size,4);
-                         end
-                        else
-                         begin
-                           cgsize:=OS_16;
-                           dec(href.offset,2);
-                           dec(size,2);
-                         end;
-                        cg.a_param_ref(exprasmlist,cgsize,href,tempcgpara);
-                      end;
-                   end
+                   cg.a_param_ref(exprasmlist,left.location.size,left.location.reference,tempcgpara)
                  else
                    begin
                      reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
@@ -294,32 +275,20 @@ implementation
          end
         else
          begin
+{$ifndef i386}
+{$warning TODO This can be removed, a_param_ref shall support this construct}
            { copy the value on the stack or use normal parameter push?
              Check for varargs first because that has no parasym }
            if not(cpf_varargs_para in callparaflags) and
               paramanager.copy_value_on_stack(parasym.varspez,left.resulttype.def,
                   aktcallnode.procdefinition.proccalloption) then
             begin
-{$ifdef i386}
-              if tempcgpara.location^.loc<>LOC_REFERENCE then
-                internalerror(200309292);
               if not (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
                 internalerror(200204241);
-              { push on stack }
-              size:=align(left.resulttype.def.size,tempcgpara.alignment);
-              if tempcgpara.location^.reference.index=NR_STACK_POINTER_REG then
-                begin
-                  cg.g_stackpointer_alloc(exprasmlist,size);
-                  reference_reset_base(href,NR_STACK_POINTER_REG,0);
-                end
-              else
-                reference_reset_base(href,tempcgpara.location^.reference.index,tempcgpara.location^.reference.offset);
-              cg.g_concatcopy(exprasmlist,left.location.reference,href,size);
-{$else i386}
               cg.a_param_copy_ref(exprasmlist,left.resulttype.def.size,left.location.reference,tempcgpara);
-{$endif i386}
             end
            else
+{$endif i386}
             begin
               case left.location.loc of
                 LOC_CONSTANT,
@@ -329,7 +298,7 @@ implementation
                 LOC_CREFERENCE :
                   begin
 {$ifndef cpu64bit}
-                    { don't call the cg64 stuff for 8-byte sized records etc }
+                    { use cg64 only for int64, not for 8 byte records }
                     if is_64bit(left.resulttype.def) then
                       cg64.a_param64_loc(exprasmlist,left.location,tempcgpara)
                     else
@@ -1260,7 +1229,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.195  2005-01-12 10:02:22  florian
+  Revision 1.196  2005-01-18 22:19:20  peter
+    * multiple location support for i386 a_param_ref
+    * remove a_param_copy_ref for i386
+
+  Revision 1.195  2005/01/12 10:02:22  florian
     * removed ie20050111
 
   Revision 1.194  2005/01/10 21:50:05  jonas

+ 18 - 9
compiler/ncgutil.pas

@@ -1362,14 +1362,19 @@ implementation
             case currpara.localloc.loc of
               LOC_REFERENCE :
                 begin
-                  href:=currpara.localloc.reference;
-                  while assigned(paraloc) do
+                  { If the parameter location is reused we don't need to copy
+                    anything }
+                  if not paramanager.param_use_paraloc(currpara.paraloc[calleeside]) then
                     begin
-                      unget_para(paraloc^);
-                      gen_load_ref(paraloc^,href,sizeleft);
-                      inc(href.offset,TCGSize2Size[paraloc^.size]);
-                      dec(sizeleft,TCGSize2Size[paraloc^.size]);
-                      paraloc:=paraloc^.next;
+                      href:=currpara.localloc.reference;
+                      while assigned(paraloc) do
+                        begin
+                          unget_para(paraloc^);
+                          gen_load_ref(paraloc^,href,sizeleft);
+                          inc(href.offset,TCGSize2Size[paraloc^.size]);
+                          dec(sizeleft,TCGSize2Size[paraloc^.size]);
+                          paraloc:=paraloc^.next;
+                        end;
                     end;
                 end;
               LOC_CREGISTER :
@@ -2040,7 +2045,7 @@ implementation
                               parasymtable :
                                 begin
                                   { Reuse the parameter location for values to are at a single location on the stack }
-                                  if (tparavarsym(sym).paraloc[calleeside].is_simple_reference) then
+                                  if paramanager.param_use_paraloc(tparavarsym(sym).paraloc[calleeside]) then
                                     begin
                                       reference_reset_base(localloc.reference,tparavarsym(sym).paraloc[calleeside].location^.reference.index,
                                           tparavarsym(sym).paraloc[calleeside].location^.reference.offset);
@@ -2349,7 +2354,11 @@ implementation
 end.
 {
   $Log$
-  Revision 1.253  2005-01-13 19:31:05  jonas
+  Revision 1.254  2005-01-18 22:19:20  peter
+    * multiple location support for i386 a_param_ref
+    * remove a_param_copy_ref for i386
+
+  Revision 1.253  2005/01/13 19:31:05  jonas
     + support LOC_VOID in gen_load_para_value()
 
   Revision 1.252  2005/01/10 21:50:05  jonas

+ 5 - 16
compiler/parabase.pas

@@ -63,7 +63,6 @@ unit parabase;
           procedure   reset;
           function    getcopy:tcgpara;
           procedure   check_simple_location;
-          function    is_simple_reference:boolean;
           function    add_location:pcgparalocation;
           procedure   get_location(var newloc:tlocation);
        end;
@@ -186,20 +185,6 @@ implementation
       end;
 
 
-    function tcgpara.is_simple_reference:boolean;
-      begin
-        if not assigned(location) then
-          internalerror(200410102);
-{$ifdef powerpc}
-        { Powerpc always needs a copy in a local temp }
-        result:=false;
-{$else}
-        result:=not assigned(location^.next) and
-                (location^.loc=LOC_REFERENCE);
-{$endif}
-      end;
-
-
     procedure tcgpara.get_location(var newloc:tlocation);
       begin
         if not assigned(location) then
@@ -267,7 +252,11 @@ end.
 
 {
    $Log$
-   Revision 1.8  2005-01-10 21:50:05  jonas
+   Revision 1.9  2005-01-18 22:19:20  peter
+     * multiple location support for i386 a_param_ref
+     * remove a_param_copy_ref for i386
+
+   Revision 1.8  2005/01/10 21:50:05  jonas
      + support for passing records in registers under darwin
      * tcgpara now also has an intsize field, which contains the size in
        bytes of the whole parameter

+ 14 - 1
compiler/paramgr.pas

@@ -40,6 +40,8 @@ unit paramgr;
           parameters. It should be overriden for each new processor
        }
        tparamanager = class
+          { true if the location in paraloc can be reused as localloc }
+          function param_use_paraloc(const cgpara:tcgpara):boolean;virtual;
           {# Returns true if the return value is actually a parameter
              pointer.
           }
@@ -129,6 +131,13 @@ implementation
        cgobj,tgobj,cgutils,
        defutil,verbose;
 
+    { true if the location in paraloc can be reused as localloc }
+    function tparamanager.param_use_paraloc(const cgpara:tcgpara):boolean;
+      begin
+        result:=false;
+      end;
+
+
     { true if uses a parameter as return value }
     function tparamanager.ret_in_param(def : tdef;calloption : tproccalloption) : boolean;
       begin
@@ -459,7 +468,11 @@ end.
 
 {
    $Log$
-   Revision 1.83  2005-01-10 21:50:05  jonas
+   Revision 1.84  2005-01-18 22:19:20  peter
+     * multiple location support for i386 a_param_ref
+     * remove a_param_copy_ref for i386
+
+   Revision 1.83  2005/01/10 21:50:05  jonas
      + support for passing records in registers under darwin
      * tcgpara now also has an intsize field, which contains the size in
        bytes of the whole parameter