浏览代码

* add a tdef to each parameter location and set it for all target
backends (not yet used, will be used in high level code generator)

git-svn-id: trunk@24761 -

Jonas Maebe 12 年之前
父节点
当前提交
7566ddcc8f

+ 46 - 11
compiler/arm/cpupara.pas

@@ -81,20 +81,25 @@ unit cpupara;
     procedure tarmparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure tarmparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym : tparavarsym;
+        pdef : tdef;
       begin
       begin
         if nr<1 then
         if nr<1 then
           internalerror(2002070801);
           internalerror(2002070801);
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
+        psym:=tparavarsym(pd.paras[nr-1]);
+        pdef:=psym.vardef;
+        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+          pdef:=getpointerdef(pdef);
         cgpara.reset;
         cgpara.reset;
-        cgpara.size:=def_cgsize(def);
+        cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.alignment:=std_param_align;
         cgpara.alignment:=std_param_align;
-        cgpara.def:=def;
+        cgpara.def:=pdef;
         paraloc:=cgpara.add_location;
         paraloc:=cgpara.add_location;
         with paraloc^ do
         with paraloc^ do
           begin
           begin
-            size:=OS_INT;
+            def:=pdef;
+            size:=def_cgsize(pdef);
             { the four first parameters are passed into registers }
             { the four first parameters are passed into registers }
             if nr<=4 then
             if nr<=4 then
               begin
               begin
@@ -362,6 +367,7 @@ unit cpupara;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_R0;
                 paraloc^.register:=NR_R0;
                 paraloc^.size:=OS_ADDR;
                 paraloc^.size:=OS_ADDR;
+                paraloc^.def:=voidpointertype;
                 break;
                 break;
               end;
               end;
 
 
@@ -413,16 +419,28 @@ unit cpupara;
                  if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
                  if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
                    case paracgsize of
                    case paracgsize of
                      OS_F32:
                      OS_F32:
-                       paraloc^.size:=OS_32;
+                       begin
+                         paraloc^.size:=OS_32;
+                         paraloc^.def:=u32inttype;
+                       end;
                      OS_F64:
                      OS_F64:
-                       paraloc^.size:=OS_32;
+                       begin
+                         paraloc^.size:=OS_32;
+                         paraloc^.def:=u32inttype;
+                       end;
                      else
                      else
                        internalerror(2005082901);
                        internalerror(2005082901);
                    end
                    end
                  else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
                  else if (paracgsize in [OS_NO,OS_64,OS_S64]) then
-                   paraloc^.size := OS_32
+                   begin
+                     paraloc^.size:=OS_32;
+                     paraloc^.def:=u32inttype;
+                   end
                  else
                  else
-                   paraloc^.size:=paracgsize;
+                   begin
+                     paraloc^.size:=paracgsize;
+                     paraloc^.def:=get_paraloc_def(paradef,paracgsize,paralen,firstparaloc);
+                   end;
                  case loc of
                  case loc of
                     LOC_REGISTER:
                     LOC_REGISTER:
                       begin
                       begin
@@ -449,6 +467,7 @@ unit cpupara;
                             { LOC_REFERENCE always contains everything that's left }
                             { LOC_REFERENCE always contains everything that's left }
                             paraloc^.loc:=LOC_REFERENCE;
                             paraloc^.loc:=LOC_REFERENCE;
                             paraloc^.size:=int_cgsize(paralen);
                             paraloc^.size:=int_cgsize(paralen);
+                            paraloc^.def:=getarraydef(u8inttype,paralen);
                             if (side=callerside) then
                             if (side=callerside) then
                               paraloc^.reference.index:=NR_STACK_POINTER_REG;
                               paraloc^.reference.index:=NR_STACK_POINTER_REG;
                             paraloc^.reference.offset:=stack_offset;
                             paraloc^.reference.offset:=stack_offset;
@@ -522,6 +541,7 @@ unit cpupara;
                             { LOC_REFERENCE always contains everything that's left }
                             { LOC_REFERENCE always contains everything that's left }
                             paraloc^.loc:=LOC_REFERENCE;
                             paraloc^.loc:=LOC_REFERENCE;
                             paraloc^.size:=int_cgsize(paralen);
                             paraloc^.size:=int_cgsize(paralen);
+                            paraloc^.def:=getarraydef(u8inttype,paralen);
                             if (side=callerside) then
                             if (side=callerside) then
                               paraloc^.reference.index:=NR_STACK_POINTER_REG;
                               paraloc^.reference.index:=NR_STACK_POINTER_REG;
                             paraloc^.reference.offset:=stack_offset;
                             paraloc^.reference.offset:=stack_offset;
@@ -534,6 +554,7 @@ unit cpupara;
                         if push_addr_param(hp.varspez,paradef,p.proccalloption) then
                         if push_addr_param(hp.varspez,paradef,p.proccalloption) then
                           begin
                           begin
                             paraloc^.size:=OS_ADDR;
                             paraloc^.size:=OS_ADDR;
+                            paraloc^.def:=getpointerdef(paradef);
                             assignintreg
                             assignintreg
                           end
                           end
                         else
                         else
@@ -545,6 +566,7 @@ unit cpupara;
                               stack_offset:=align(stack_offset,8);
                               stack_offset:=align(stack_offset,8);
 
 
                              paraloc^.size:=paracgsize;
                              paraloc^.size:=paracgsize;
+                             paraloc^.def:=paradef;
                              paraloc^.loc:=LOC_REFERENCE;
                              paraloc^.loc:=LOC_REFERENCE;
                              paraloc^.reference.index:=NR_STACK_POINTER_REG;
                              paraloc^.reference.index:=NR_STACK_POINTER_REG;
                              paraloc^.reference.offset:=stack_offset;
                              paraloc^.reference.offset:=stack_offset;
@@ -621,6 +643,7 @@ unit cpupara;
                     internalerror(2012032501);
                     internalerror(2012032501);
                 end;
                 end;
                 paraloc^.size:=retcgsize;
                 paraloc^.size:=retcgsize;
+                paraloc^.def:=result.def;
               end
               end
             else if (p.proccalloption in [pocall_softfloat]) or
             else if (p.proccalloption in [pocall_softfloat]) or
                (cs_fp_emulation in current_settings.moduleswitches) or
                (cs_fp_emulation in current_settings.moduleswitches) or
@@ -636,6 +659,7 @@ unit cpupara;
                       else
                       else
                         paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
                         paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
                       paraloc^.size:=OS_32;
                       paraloc^.size:=OS_32;
+                      paraloc^.def:=u32inttype;
                       paraloc:=result.add_location;
                       paraloc:=result.add_location;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.loc:=LOC_REGISTER;
                       if target_info.endian = endian_big then
                       if target_info.endian = endian_big then
@@ -643,6 +667,7 @@ unit cpupara;
                       else
                       else
                         paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
                         paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
                       paraloc^.size:=OS_32;
                       paraloc^.size:=OS_32;
+                      paraloc^.def:=u32inttype;
                     end;
                     end;
                   OS_32,
                   OS_32,
                   OS_F32:
                   OS_F32:
@@ -650,6 +675,7 @@ unit cpupara;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.register:=NR_FUNCTION_RETURN_REG;
                       paraloc^.register:=NR_FUNCTION_RETURN_REG;
                       paraloc^.size:=OS_32;
                       paraloc^.size:=OS_32;
+                      paraloc^.def:=u32inttype;
                     end;
                     end;
                   else
                   else
                     internalerror(2005082603);
                     internalerror(2005082603);
@@ -660,6 +686,7 @@ unit cpupara;
                 paraloc^.loc:=LOC_FPUREGISTER;
                 paraloc^.loc:=LOC_FPUREGISTER;
                 paraloc^.register:=NR_FPU_RESULT_REG;
                 paraloc^.register:=NR_FPU_RESULT_REG;
                 paraloc^.size:=retcgsize;
                 paraloc^.size:=retcgsize;
+                paraloc^.def:=result.def;
               end;
               end;
           end
           end
           { Return in register }
           { Return in register }
@@ -673,6 +700,7 @@ unit cpupara;
                 else
                 else
                   paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
                   paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
                 paraloc^.size:=OS_32;
                 paraloc^.size:=OS_32;
+                paraloc^.def:=u32inttype;
                 paraloc:=result.add_location;
                 paraloc:=result.add_location;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 if target_info.endian = endian_big then
                 if target_info.endian = endian_big then
@@ -680,15 +708,22 @@ unit cpupara;
                 else
                 else
                   paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
                   paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
                 paraloc^.size:=OS_32;
                 paraloc^.size:=OS_32;
+                paraloc^.def:=u32inttype;
               end
               end
             else
             else
               begin
               begin
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_FUNCTION_RETURN_REG;
                 paraloc^.register:=NR_FUNCTION_RETURN_REG;
                 if (result.intsize<>3) then
                 if (result.intsize<>3) then
-                  paraloc^.size:=retcgsize
+                  begin
+                    paraloc^.size:=retcgsize;
+                    paraloc^.def:=result.def;
+                  end
                 else
                 else
-                  paraloc^.size:=OS_32;
+                  begin
+                    paraloc^.size:=OS_32;
+                    paraloc^.def:=u32inttype;
+                  end;
               end;
               end;
           end;
           end;
       end;
       end;

+ 44 - 10
compiler/avr/cpupara.pas

@@ -71,20 +71,25 @@ unit cpupara;
     procedure tavrparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure tavrparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym: tparavarsym;
+        pdef: tdef;
       begin
       begin
         if nr<1 then
         if nr<1 then
           internalerror(2002070801);
           internalerror(2002070801);
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
+        psym:=tparavarsym(pd.paras[nr-1]);
+        pdef:=psym.vardef;
+        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+          pdef:=getpointerdef(pdef);
         cgpara.reset;
         cgpara.reset;
-        cgpara.size:=def_cgsize(def);
+        cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.alignment:=std_param_align;
         cgpara.alignment:=std_param_align;
-        cgpara.def:=def;
+        cgpara.def:=pdef;
         paraloc:=cgpara.add_location;
         paraloc:=cgpara.add_location;
         with paraloc^ do
         with paraloc^ do
           begin
           begin
-            size:=OS_INT;
+            size:=def_cgsize(pdef);
+            def:=pdef;
             { the four first parameters are passed into registers }
             { the four first parameters are passed into registers }
             if nr<=9 then
             if nr<=9 then
               begin
               begin
@@ -225,6 +230,7 @@ unit cpupara;
         paracgsize   : tcgsize;
         paracgsize   : tcgsize;
         paralen : longint;
         paralen : longint;
         i : integer;
         i : integer;
+        firstparaloc: boolean;
 
 
       procedure assignintreg;
       procedure assignintreg;
         begin
         begin
@@ -272,6 +278,7 @@ unit cpupara;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_R25;
                 paraloc^.register:=NR_R25;
                 paraloc^.size:=OS_ADDR;
                 paraloc^.size:=OS_ADDR;
+                paraloc^.def:=voidpointertype;
                 break;
                 break;
               end;
               end;
 
 
@@ -315,6 +322,7 @@ unit cpupara;
              if paralen=0 then
              if paralen=0 then
                internalerror(200410311);
                internalerror(200410311);
 {$endif EXTDEBUG}
 {$endif EXTDEBUG}
+             firstparaloc:=true;
              while paralen>0 do
              while paralen>0 do
                begin
                begin
                  paraloc:=hp.paraloc[side].add_location;
                  paraloc:=hp.paraloc[side].add_location;
@@ -322,16 +330,28 @@ unit cpupara;
                  if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
                  if (loc=LOC_REGISTER) and (paracgsize in [OS_F32,OS_F64,OS_F80]) then
                    case paracgsize of
                    case paracgsize of
                      OS_F32:
                      OS_F32:
-                       paraloc^.size:=OS_32;
+                       begin
+                         paraloc^.size:=OS_32;
+                         paraloc^.def:=u32inttype;
+                       end;
                      OS_F64:
                      OS_F64:
-                       paraloc^.size:=OS_32;
+                       begin
+                         paraloc^.size:=OS_32;
+                         paraloc^.def:=u32inttype;
+                       end;
                      else
                      else
                        internalerror(2005082901);
                        internalerror(2005082901);
                    end
                    end
                  else if paracgsize<>OS_S8 then
                  else if paracgsize<>OS_S8 then
-                   paraloc^.size := OS_8
+                   begin
+                     paraloc^.size:=OS_8;
+                     paraloc^.def:=u8inttype
+                   end
                  else
                  else
-                   paraloc^.size:=paracgsize;
+                   begin
+                     paraloc^.size:=paracgsize;
+                     paraloc^.def:=paradef;
+                   end;
                  case loc of
                  case loc of
                     LOC_REGISTER:
                     LOC_REGISTER:
                       begin
                       begin
@@ -346,6 +366,8 @@ unit cpupara;
                             { LOC_REFERENCE covers always the overleft }
                             { LOC_REFERENCE covers always the overleft }
                             paraloc^.loc:=LOC_REFERENCE;
                             paraloc^.loc:=LOC_REFERENCE;
                             paraloc^.size:=int_cgsize(paralen);
                             paraloc^.size:=int_cgsize(paralen);
+                            paraloc^.def:=get_paraloc_def(paradef,paracgsize,paralen,firstparaloc);
+
                             if (side=callerside) then
                             if (side=callerside) then
                               paraloc^.reference.index:=NR_STACK_POINTER_REG;
                               paraloc^.reference.index:=NR_STACK_POINTER_REG;
                             paraloc^.reference.offset:=stack_offset;
                             paraloc^.reference.offset:=stack_offset;
@@ -357,9 +379,13 @@ unit cpupara;
                       begin
                       begin
                         paraloc^.size:=OS_ADDR;
                         paraloc^.size:=OS_ADDR;
                         if push_addr_param(hp.varspez,paradef,p.proccalloption) then
                         if push_addr_param(hp.varspez,paradef,p.proccalloption) then
-                          assignintreg
+                          begin
+                            paraloc^.def:=getpointerdef(paradef);
+                            assignintreg
+                          end
                         else
                         else
                           begin
                           begin
+                             paraloc^.def:=hp.vardef;
                              paraloc^.loc:=LOC_REFERENCE;
                              paraloc^.loc:=LOC_REFERENCE;
                              paraloc^.reference.index:=NR_STACK_POINTER_REG;
                              paraloc^.reference.index:=NR_STACK_POINTER_REG;
                              paraloc^.reference.offset:=stack_offset;
                              paraloc^.reference.offset:=stack_offset;
@@ -378,6 +404,7 @@ unit cpupara;
                        end;
                        end;
                    end;
                    end;
                  dec(paralen,tcgsize2size[paraloc^.size]);
                  dec(paralen,tcgsize2size[paraloc^.size]);
+                 firstparaloc:=false;
                end;
                end;
           end;
           end;
         curintreg:=nextintreg;
         curintreg:=nextintreg;
@@ -424,10 +451,12 @@ unit cpupara;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
                       paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
                       paraloc^.size:=OS_32;
                       paraloc^.size:=OS_32;
+                      paraloc^.def:=u32inttype;
                       paraloc:=result.add_location;
                       paraloc:=result.add_location;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
                       paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
                       paraloc^.size:=OS_32;
                       paraloc^.size:=OS_32;
+                      paraloc^.def:=u32inttype;
                     end;
                     end;
                   OS_32,
                   OS_32,
                   OS_F32:
                   OS_F32:
@@ -435,6 +464,7 @@ unit cpupara;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.register:=NR_FUNCTION_RETURN_REG;
                       paraloc^.register:=NR_FUNCTION_RETURN_REG;
                       paraloc^.size:=OS_32;
                       paraloc^.size:=OS_32;
+                      paraloc^.def:=u32inttype;
                     end;
                     end;
                   else
                   else
                     internalerror(2005082603);
                     internalerror(2005082603);
@@ -445,6 +475,7 @@ unit cpupara;
                 paraloc^.loc:=LOC_FPUREGISTER;
                 paraloc^.loc:=LOC_FPUREGISTER;
                 paraloc^.register:=NR_FPU_RESULT_REG;
                 paraloc^.register:=NR_FPU_RESULT_REG;
                 paraloc^.size:=retcgsize;
                 paraloc^.size:=retcgsize;
+                paraloc^.def:=result.def;
               end;
               end;
           end
           end
           { Return in register }
           { Return in register }
@@ -455,16 +486,19 @@ unit cpupara;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
                 paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG;
                 paraloc^.size:=OS_32;
                 paraloc^.size:=OS_32;
+                paraloc^.def:=u32inttype;
                 paraloc:=result.add_location;
                 paraloc:=result.add_location;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
                 paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG;
                 paraloc^.size:=OS_32;
                 paraloc^.size:=OS_32;
+                paraloc^.def:=u32inttype;
               end
               end
             else
             else
               begin
               begin
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_FUNCTION_RETURN_REG;
                 paraloc^.register:=NR_FUNCTION_RETURN_REG;
                 paraloc^.size:=OS_32;
                 paraloc^.size:=OS_32;
+                paraloc^.def:=u32inttype;
               end;
               end;
           end;
           end;
       end;
       end;

+ 43 - 11
compiler/i386/cpupara.pas

@@ -277,18 +277,23 @@ unit cpupara;
     procedure ti386paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure ti386paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym: tparavarsym;
+        pdef: tdef;
       begin
       begin
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
+        psym:=tparavarsym(pd.paras[nr-1]);
+        pdef:=psym.vardef;
+        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+          pdef:=getpointerdef(pdef);
         cgpara.reset;
         cgpara.reset;
-        cgpara.size:=def_cgsize(def);
+        cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.alignment:=get_para_align(pd.proccalloption);
         cgpara.alignment:=get_para_align(pd.proccalloption);
-        cgpara.def:=def;
+        cgpara.def:=pdef;
         paraloc:=cgpara.add_location;
         paraloc:=cgpara.add_location;
         with paraloc^ do
         with paraloc^ do
          begin
          begin
-           size:=OS_INT;
+           size:=def_cgsize(pdef);
+           def:=pdef;
            if pd.proccalloption=pocall_register then
            if pd.proccalloption=pocall_register then
              begin
              begin
                if (nr<=length(parasupregs)) then
                if (nr<=length(parasupregs)) then
@@ -367,6 +372,7 @@ unit cpupara;
             paraloc^.loc:=LOC_FPUREGISTER;
             paraloc^.loc:=LOC_FPUREGISTER;
             paraloc^.register:=NR_FPU_RESULT_REG;
             paraloc^.register:=NR_FPU_RESULT_REG;
             paraloc^.size:=retcgsize;
             paraloc^.size:=retcgsize;
+            paraloc^.def:=result.def;
           end
           end
         else
         else
          { Return in register }
          { Return in register }
@@ -381,6 +387,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
 
 
                { high 32bits }
                { high 32bits }
                paraloc:=result.add_location;
                paraloc:=result.add_location;
@@ -390,10 +397,12 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
              end
              end
             else
             else
              begin
              begin
                paraloc^.size:=retcgsize;
                paraloc^.size:=retcgsize;
+               paraloc^.def:=result.def;
                if side=callerside then
                if side=callerside then
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
                else
@@ -413,8 +422,9 @@ unit cpupara;
         paralen,
         paralen,
         varalign   : longint;
         varalign   : longint;
         paraalign  : shortint;
         paraalign  : shortint;
-        pushaddr   : boolean;
         paracgsize : tcgsize;
         paracgsize : tcgsize;
+        firstparaloc,
+        pushaddr   : boolean;
       begin
       begin
         paraalign:=get_para_align(p.proccalloption);
         paraalign:=get_para_align(p.proccalloption);
         { we push Flags and CS as long
         { we push Flags and CS as long
@@ -476,6 +486,7 @@ unit cpupara;
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc^.loc:=LOC_REFERENCE;
                 paraloc^.loc:=LOC_REFERENCE;
                 paraloc^.size:=paracgsize;
                 paraloc^.size:=paracgsize;
+                paraloc^.def:=paradef;
                 if side=callerside then
                 if side=callerside then
                   paraloc^.reference.index:=NR_STACK_POINTER_REG
                   paraloc^.reference.index:=NR_STACK_POINTER_REG
                 else
                 else
@@ -497,6 +508,7 @@ unit cpupara;
               begin
               begin
                 if paralen=0 then
                 if paralen=0 then
                   internalerror(200501163);
                   internalerror(200501163);
+                firstparaloc:=true;
                 while (paralen>0) do
                 while (paralen>0) do
                   begin
                   begin
                     paraloc:=hp.paraloc[side].add_location;
                     paraloc:=hp.paraloc[side].add_location;
@@ -505,15 +517,22 @@ unit cpupara;
                     if (paracgsize in [OS_F64,OS_F32]) then
                     if (paracgsize in [OS_F64,OS_F32]) then
                       begin
                       begin
                         paraloc^.size:=paracgsize;
                         paraloc^.size:=paracgsize;
+                        paraloc^.def:=paradef;
                         l:=paralen;
                         l:=paralen;
                       end
                       end
                     else
                     else
                       begin
                       begin
                         { We can allocate at maximum 32 bits per location }
                         { We can allocate at maximum 32 bits per location }
                         if paralen>sizeof(aint) then
                         if paralen>sizeof(aint) then
-                          l:=sizeof(aint)
+                          begin
+                            l:=sizeof(aint);
+                            paraloc^.def:=uinttype;
+                          end
                         else
                         else
-                          l:=paralen;
+                          begin
+                            l:=paralen;
+                            paraloc^.def:=get_paraloc_def(paradef,paracgsize,l,firstparaloc);
+                          end;
                         paraloc^.size:=int_cgsize(l);
                         paraloc^.size:=int_cgsize(l);
                       end;
                       end;
                     if (side=callerside) or
                     if (side=callerside) or
@@ -531,6 +550,7 @@ unit cpupara;
                         inc(paraloc^.reference.offset,4);
                         inc(paraloc^.reference.offset,4);
                     parasize:=align(parasize+l,varalign);
                     parasize:=align(parasize+l,varalign);
                     dec(paralen,l);
                     dec(paralen,l);
+                    firstparaloc:=false;
                   end;
                   end;
               end;
               end;
             if p.proccalloption in pushleftright_pocalls then
             if p.proccalloption in pushleftright_pocalls then
@@ -552,9 +572,10 @@ unit cpupara;
         l,
         l,
         paralen,
         paralen,
         varalign : longint;
         varalign : longint;
-        pushaddr : boolean;
         paraalign : shortint;
         paraalign : shortint;
         pass : byte;
         pass : byte;
+        firstparaloc,
+        pushaddr : boolean;
       begin
       begin
         if paras.count=0 then
         if paras.count=0 then
           exit;
           exit;
@@ -621,6 +642,7 @@ unit cpupara;
                           begin
                           begin
                             paraloc:=hp.paraloc[side].add_location;
                             paraloc:=hp.paraloc[side].add_location;
                             paraloc^.size:=paracgsize;
                             paraloc^.size:=paracgsize;
+                            paraloc^.def:=paradef;
                             paraloc^.loc:=LOC_REGISTER;
                             paraloc^.loc:=LOC_REGISTER;
                             paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
                             paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
                             inc(parareg);
                             inc(parareg);
@@ -636,6 +658,7 @@ unit cpupara;
                               paraloc:=hp.paraloc[side].add_location;
                               paraloc:=hp.paraloc[side].add_location;
                               paraloc^.loc:=LOC_REFERENCE;
                               paraloc^.loc:=LOC_REFERENCE;
                               paraloc^.size:=paracgsize;
                               paraloc^.size:=paracgsize;
+                              paraloc^.def:=paradef;
                               if side=callerside then
                               if side=callerside then
                                 paraloc^.reference.index:=NR_STACK_POINTER_REG
                                 paraloc^.reference.index:=NR_STACK_POINTER_REG
                               else
                               else
@@ -650,6 +673,7 @@ unit cpupara;
                             begin
                             begin
                               if paralen=0 then
                               if paralen=0 then
                                 internalerror(200501163);
                                 internalerror(200501163);
+                              firstparaloc:=true;
                               while (paralen>0) do
                               while (paralen>0) do
                                 begin
                                 begin
                                   paraloc:=hp.paraloc[side].add_location;
                                   paraloc:=hp.paraloc[side].add_location;
@@ -658,15 +682,22 @@ unit cpupara;
                                   if (paracgsize in [OS_F64,OS_F32]) then
                                   if (paracgsize in [OS_F64,OS_F32]) then
                                     begin
                                     begin
                                       paraloc^.size:=paracgsize;
                                       paraloc^.size:=paracgsize;
+                                      paraloc^.def:=paradef;
                                       l:=paralen;
                                       l:=paralen;
                                     end
                                     end
                                   else
                                   else
                                     begin
                                     begin
                                       { We can allocate at maximum 32 bits per location }
                                       { We can allocate at maximum 32 bits per location }
                                       if paralen>sizeof(aint) then
                                       if paralen>sizeof(aint) then
-                                        l:=sizeof(aint)
+                                        begin
+                                          l:=sizeof(aint);
+                                          paraloc^.def:=uinttype;
+                                        end
                                       else
                                       else
-                                        l:=paralen;
+                                        begin
+                                          l:=paralen;
+                                          paraloc^.def:=get_paraloc_def(paradef,paracgsize,l,firstparaloc);
+                                        end;
                                       paraloc^.size:=int_cgsize(l);
                                       paraloc^.size:=int_cgsize(l);
                                     end;
                                     end;
                                   if side=callerside then
                                   if side=callerside then
@@ -679,6 +710,7 @@ unit cpupara;
                                     inc(paraloc^.reference.offset,target_info.first_parm_offset);
                                     inc(paraloc^.reference.offset,target_info.first_parm_offset);
                                   parasize:=align(parasize+l,varalign);
                                   parasize:=align(parasize+l,varalign);
                                   dec(paralen,l);
                                   dec(paralen,l);
+                                  firstparaloc:=false;
                                 end;
                                 end;
                             end;
                             end;
                         end;
                         end;

+ 46 - 10
compiler/i8086/cpupara.pas

@@ -231,18 +231,23 @@ unit cpupara;
     procedure ti8086paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure ti8086paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym: tparavarsym;
+        pdef : tdef;
       begin
       begin
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
+        psym:=tparavarsym(pd.paras[nr-1]);
+        pdef:=psym.vardef;
+        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+          pdef:=getpointerdef(pdef);
         cgpara.reset;
         cgpara.reset;
-        cgpara.size:=def_cgsize(def);
+        cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.alignment:=get_para_align(pd.proccalloption);
         cgpara.alignment:=get_para_align(pd.proccalloption);
-        cgpara.def:=def;
+        cgpara.def:=pdef;
         paraloc:=cgpara.add_location;
         paraloc:=cgpara.add_location;
         with paraloc^ do
         with paraloc^ do
          begin
          begin
-           size:=OS_INT;
+           size:=def_cgsize(pdef);
+           def:=pdef;
            if pd.proccalloption=pocall_register then
            if pd.proccalloption=pocall_register then
              begin
              begin
                if (nr<=length(parasupregs)) then
                if (nr<=length(parasupregs)) then
@@ -321,6 +326,7 @@ unit cpupara;
             paraloc^.loc:=LOC_FPUREGISTER;
             paraloc^.loc:=LOC_FPUREGISTER;
             paraloc^.register:=NR_FPU_RESULT_REG;
             paraloc^.register:=NR_FPU_RESULT_REG;
             paraloc^.size:=retcgsize;
             paraloc^.size:=retcgsize;
+            paraloc^.def:=result.def;
           end
           end
         else
         else
          { Return in register }
          { Return in register }
@@ -335,6 +341,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                paraloc^.size:=OS_16;
                paraloc^.size:=OS_16;
+               paraloc^.def:=u16inttype;
 
 
                { bits 16..31 }
                { bits 16..31 }
                paraloc:=result.add_location;
                paraloc:=result.add_location;
@@ -344,6 +351,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                paraloc^.size:=OS_16;
                paraloc^.size:=OS_16;
+               paraloc^.def:=u16inttype;
 
 
                { bits 32..47 }
                { bits 32..47 }
                paraloc:=result.add_location;
                paraloc:=result.add_location;
@@ -353,6 +361,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGHER_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGHER_REG;
                paraloc^.size:=OS_16;
                paraloc^.size:=OS_16;
+               paraloc^.def:=u16inttype;
 
 
                { bits 48..63 }
                { bits 48..63 }
                paraloc:=result.add_location;
                paraloc:=result.add_location;
@@ -362,6 +371,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGHEST_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGHEST_REG;
                paraloc^.size:=OS_16;
                paraloc^.size:=OS_16;
+               paraloc^.def:=u16inttype;
              end
              end
             else if retcgsize in [OS_32,OS_S32] then
             else if retcgsize in [OS_32,OS_S32] then
              begin
              begin
@@ -371,6 +381,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN32_LOW_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN32_LOW_REG;
                paraloc^.size:=OS_16;
                paraloc^.size:=OS_16;
+               paraloc^.def:=u16inttype;
 
 
                { high 16bits }
                { high 16bits }
                paraloc:=result.add_location;
                paraloc:=result.add_location;
@@ -380,10 +391,12 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN32_HIGH_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN32_HIGH_REG;
                paraloc^.size:=OS_16;
                paraloc^.size:=OS_16;
+               paraloc^.def:=u16inttype;
              end
              end
             else
             else
              begin
              begin
                paraloc^.size:=retcgsize;
                paraloc^.size:=retcgsize;
+               paraloc^.def:=result.def;
                if side=callerside then
                if side=callerside then
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
                else
@@ -403,8 +416,9 @@ unit cpupara;
         paralen,
         paralen,
         varalign   : longint;
         varalign   : longint;
         paraalign  : shortint;
         paraalign  : shortint;
-        pushaddr   : boolean;
         paracgsize : tcgsize;
         paracgsize : tcgsize;
+        firstparaloc,
+        pushaddr   : boolean;
       begin
       begin
         paraalign:=get_para_align(p.proccalloption);
         paraalign:=get_para_align(p.proccalloption);
         { we push Flags and CS as long
         { we push Flags and CS as long
@@ -466,6 +480,7 @@ unit cpupara;
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc^.loc:=LOC_REFERENCE;
                 paraloc^.loc:=LOC_REFERENCE;
                 paraloc^.size:=paracgsize;
                 paraloc^.size:=paracgsize;
+                paraloc^.def:=paradef;
                 if side=callerside then
                 if side=callerside then
                   paraloc^.reference.index:=NR_STACK_POINTER_REG
                   paraloc^.reference.index:=NR_STACK_POINTER_REG
                 else
                 else
@@ -487,6 +502,7 @@ unit cpupara;
               begin
               begin
                 if paralen=0 then
                 if paralen=0 then
                   internalerror(200501163);
                   internalerror(200501163);
+                firstparaloc:=true;
                 while (paralen>0) do
                 while (paralen>0) do
                   begin
                   begin
                     paraloc:=hp.paraloc[side].add_location;
                     paraloc:=hp.paraloc[side].add_location;
@@ -495,15 +511,22 @@ unit cpupara;
                     if (paracgsize in [OS_F64,OS_F32]) then
                     if (paracgsize in [OS_F64,OS_F32]) then
                       begin
                       begin
                         paraloc^.size:=paracgsize;
                         paraloc^.size:=paracgsize;
+                        paraloc^.def:=paradef;
                         l:=paralen;
                         l:=paralen;
                       end
                       end
                     else
                     else
                       begin
                       begin
                         { We can allocate at maximum 32 bits per location }
                         { We can allocate at maximum 32 bits per location }
                         if paralen>sizeof(aint) then
                         if paralen>sizeof(aint) then
-                          l:=sizeof(aint)
+                          begin
+                            l:=sizeof(aint);
+                            paraloc^.def:=uinttype;
+                          end
                         else
                         else
-                          l:=paralen;
+                          begin
+                            l:=paralen;
+                            paraloc^.def:=get_paraloc_def(paradef,paracgsize,l,firstparaloc);
+                          end;
                         paraloc^.size:=int_cgsize(l);
                         paraloc^.size:=int_cgsize(l);
                       end;
                       end;
                     if (side=callerside) or
                     if (side=callerside) or
@@ -521,6 +544,7 @@ unit cpupara;
                         inc(paraloc^.reference.offset,4);
                         inc(paraloc^.reference.offset,4);
                     parasize:=align(parasize+l,varalign);
                     parasize:=align(parasize+l,varalign);
                     dec(paralen,l);
                     dec(paralen,l);
+                    firstparaloc:=false;
                   end;
                   end;
               end;
               end;
             if p.proccalloption in pushleftright_pocalls then
             if p.proccalloption in pushleftright_pocalls then
@@ -545,6 +569,7 @@ unit cpupara;
         pushaddr : boolean;
         pushaddr : boolean;
         paraalign : shortint;
         paraalign : shortint;
         pass : byte;
         pass : byte;
+        firstparaloc : boolean;
       begin
       begin
         if paras.count=0 then
         if paras.count=0 then
           exit;
           exit;
@@ -611,6 +636,7 @@ unit cpupara;
                           begin
                           begin
                             paraloc:=hp.paraloc[side].add_location;
                             paraloc:=hp.paraloc[side].add_location;
                             paraloc^.size:=paracgsize;
                             paraloc^.size:=paracgsize;
+                            paraloc^.def:=paradef;
                             paraloc^.loc:=LOC_REGISTER;
                             paraloc^.loc:=LOC_REGISTER;
                             paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
                             paraloc^.register:=newreg(R_INTREGISTER,parasupregs[parareg],cgsize2subreg(R_INTREGISTER,paracgsize));
                             inc(parareg);
                             inc(parareg);
@@ -626,6 +652,7 @@ unit cpupara;
                               paraloc:=hp.paraloc[side].add_location;
                               paraloc:=hp.paraloc[side].add_location;
                               paraloc^.loc:=LOC_REFERENCE;
                               paraloc^.loc:=LOC_REFERENCE;
                               paraloc^.size:=paracgsize;
                               paraloc^.size:=paracgsize;
+                              paraloc^.def:=paradef;
                               if side=callerside then
                               if side=callerside then
                                 paraloc^.reference.index:=NR_STACK_POINTER_REG
                                 paraloc^.reference.index:=NR_STACK_POINTER_REG
                               else
                               else
@@ -640,6 +667,7 @@ unit cpupara;
                             begin
                             begin
                               if paralen=0 then
                               if paralen=0 then
                                 internalerror(200501163);
                                 internalerror(200501163);
+                              firstparaloc:=true;
                               while (paralen>0) do
                               while (paralen>0) do
                                 begin
                                 begin
                                   paraloc:=hp.paraloc[side].add_location;
                                   paraloc:=hp.paraloc[side].add_location;
@@ -648,15 +676,22 @@ unit cpupara;
                                   if (paracgsize in [OS_F64,OS_F32]) then
                                   if (paracgsize in [OS_F64,OS_F32]) then
                                     begin
                                     begin
                                       paraloc^.size:=paracgsize;
                                       paraloc^.size:=paracgsize;
+                                      paraloc^.def:=paradef;
                                       l:=paralen;
                                       l:=paralen;
                                     end
                                     end
                                   else
                                   else
                                     begin
                                     begin
                                       { We can allocate at maximum 32 bits per location }
                                       { We can allocate at maximum 32 bits per location }
                                       if paralen>sizeof(aint) then
                                       if paralen>sizeof(aint) then
-                                        l:=sizeof(aint)
+                                        begin
+                                          l:=sizeof(aint);
+                                          paraloc^.def:=uinttype;
+                                        end
                                       else
                                       else
-                                        l:=paralen;
+                                        begin
+                                          l:=paralen;
+                                          paraloc^.def:=get_paraloc_def(paradef,paracgsize,l,firstparaloc);
+                                        end;
                                       paraloc^.size:=int_cgsize(l);
                                       paraloc^.size:=int_cgsize(l);
                                     end;
                                     end;
                                   if side=callerside then
                                   if side=callerside then
@@ -669,6 +704,7 @@ unit cpupara;
                                     inc(paraloc^.reference.offset,target_info.first_parm_offset);
                                     inc(paraloc^.reference.offset,target_info.first_parm_offset);
                                   parasize:=align(parasize+l,varalign);
                                   parasize:=align(parasize+l,varalign);
                                   dec(paralen,l);
                                   dec(paralen,l);
+                                  firstparaloc:=false;
                                 end;
                                 end;
                             end;
                             end;
                         end;
                         end;

+ 15 - 0
compiler/jvm/cpupara.pas

@@ -147,6 +147,7 @@ implementation
             result.size:=OS_NO;
             result.size:=OS_NO;
             result.intsize:=0;
             result.intsize:=0;
             paraloc^.size:=OS_NO;
             paraloc^.size:=OS_NO;
+            paraloc^.def:=voidtype;
             paraloc^.loc:=LOC_VOID;
             paraloc^.loc:=LOC_VOID;
             exit;
             exit;
           end;
           end;
@@ -156,6 +157,11 @@ implementation
             retcgsize:=OS_INT;
             retcgsize:=OS_INT;
             result.intsize:=sizeof(pint);
             result.intsize:=sizeof(pint);
           end
           end
+        else if jvmimplicitpointertype(result.def) then
+          begin
+            retcgsize:=OS_ADDR;
+            result.def:=getpointerdef(result.def);
+          end
         else
         else
           begin
           begin
             retcgsize:=def_cgsize(result.def);
             retcgsize:=def_cgsize(result.def);
@@ -168,6 +174,8 @@ implementation
         paraloc^.loc:=LOC_REFERENCE;
         paraloc^.loc:=LOC_REFERENCE;
         paraloc^.reference.index:=NR_EVAL_STACK_BASE;
         paraloc^.reference.index:=NR_EVAL_STACK_BASE;
         paraloc^.reference.offset:=0;
         paraloc^.reference.offset:=0;
+        paraloc^.size:=result.size;
+        paraloc^.def:=result.def;
       end;
       end;
 
 
     function TJVMParaManager.param_use_paraloc(const cgpara: tcgpara): boolean;
     function TJVMParaManager.param_use_paraloc(const cgpara: tcgpara): boolean;
@@ -226,6 +234,11 @@ implementation
                 paracgsize:=OS_ADDR;
                 paracgsize:=OS_ADDR;
                 paradef:=java_jlobject;
                 paradef:=java_jlobject;
               end
               end
+            else if jvmimplicitpointertype(hp.vardef) then
+              begin
+                paracgsize:=OS_ADDR;
+                paradef:=getpointerdef(hp.vardef);
+              end
             else
             else
               begin
               begin
                 paracgsize:=def_cgsize(hp.vardef);
                 paracgsize:=def_cgsize(hp.vardef);
@@ -246,6 +259,8 @@ implementation
               taking up two slots) }
               taking up two slots) }
             paraloc^.loc:=LOC_REFERENCE;;
             paraloc^.loc:=LOC_REFERENCE;;
             paraloc^.reference.offset:=paraofs;
             paraloc^.reference.offset:=paraofs;
+            paraloc^.size:=paracgsize;
+            paraloc^.def:=paradef;
             case side of
             case side of
               callerside:
               callerside:
                 begin
                 begin

+ 20 - 5
compiler/m68k/cpupara.pas

@@ -68,16 +68,20 @@ unit cpupara;
     procedure tm68kparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure tm68kparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym: tparavarsym;
+        pdef: tdef;
       begin
       begin
          if nr<1 then
          if nr<1 then
            internalerror(2002070801);
            internalerror(2002070801);
-         def:=tparavarsym(pd.paras[nr-1]).vardef;
+         psym:=tparavarsym(pd.paras[nr-1]);
+         pdef:=psym.vardef;
+         if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+           pdef:=getpointerdef(pdef);
          cgpara.reset;
          cgpara.reset;
-         cgpara.size:=def_cgsize(def);
+         cgpara.size:=def_cgsize(pdef);
          cgpara.intsize:=tcgsize2size[cgpara.size];
          cgpara.intsize:=tcgsize2size[cgpara.size];
          cgpara.alignment:=std_param_align;
          cgpara.alignment:=std_param_align;
-         cgpara.def:=def;
+         cgpara.def:=pdef;
          paraloc:=cgpara.add_location;
          paraloc:=cgpara.add_location;
          with paraloc^ do
          with paraloc^ do
            begin
            begin
@@ -87,7 +91,8 @@ unit cpupara;
               loc:=LOC_REFERENCE;
               loc:=LOC_REFERENCE;
               reference.index:=NR_STACK_POINTER_REG;
               reference.index:=NR_STACK_POINTER_REG;
               reference.offset:=target_info.first_parm_offset+nr*4;
               reference.offset:=target_info.first_parm_offset+nr*4;
-              size:=OS_INT;
+              size:=def_cgsize(pdef);
+              def:=pdef;
            end;
            end;
       end;
       end;
 
 
@@ -206,6 +211,7 @@ unit cpupara;
             paraloc^.loc:=LOC_FPUREGISTER;
             paraloc^.loc:=LOC_FPUREGISTER;
             paraloc^.register:=NR_FPU_RESULT_REG;
             paraloc^.register:=NR_FPU_RESULT_REG;
             paraloc^.size:=retcgsize;
             paraloc^.size:=retcgsize;
+            paraloc^.def:=result.def;
           end
           end
         else
         else
          { Return in register }
          { Return in register }
@@ -215,6 +221,7 @@ unit cpupara;
                { low 32bits }
                { low 32bits }
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
                if side=callerside then
                if side=callerside then
                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
                  paraloc^.register:=NR_FUNCTION_RESULT64_LOW_REG
                else
                else
@@ -223,6 +230,7 @@ unit cpupara;
                paraloc:=result.add_location;
                paraloc:=result.add_location;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
                if side=calleeside then
                if side=calleeside then
                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
                  paraloc^.register:=NR_FUNCTION_RESULT64_HIGH_REG
                else
                else
@@ -232,6 +240,7 @@ unit cpupara;
              begin
              begin
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.size:=retcgsize;
                paraloc^.size:=retcgsize;
+               paraloc^.def:=result.def;
                if side=callerside then
                if side=callerside then
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
                else
@@ -266,6 +275,7 @@ unit cpupara;
 	nextintreg,
 	nextintreg,
 	nextfloatreg : tsuperregister;
 	nextfloatreg : tsuperregister;
 	stack_offset : longint;
 	stack_offset : longint;
+        firstparaloc : boolean;
 
 
       begin
       begin
         result:=0;
         result:=0;
@@ -301,6 +311,7 @@ unit cpupara;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
 		paraloc^.register:=NR_D0;
 		paraloc^.register:=NR_D0;
                 paraloc^.size:=OS_ADDR;
                 paraloc^.size:=OS_ADDR;
+                paraloc^.def:=voidpointertype;
                 break;
                 break;
               end;
               end;
 
 
@@ -344,6 +355,7 @@ unit cpupara;
                 end
                 end
               else
               else
                 internalerror(200506052);
                 internalerror(200506052);
+            firstparaloc:=true;
             { can become < 0 for e.g. 3-byte records }
             { can become < 0 for e.g. 3-byte records }
             while (paralen > 0) do
             while (paralen > 0) do
               begin
               begin
@@ -384,6 +396,7 @@ unit cpupara;
 {$endif DEBUG_CHARLIE}
 {$endif DEBUG_CHARLIE}
                     paraloc^.loc:=LOC_REFERENCE;
                     paraloc^.loc:=LOC_REFERENCE;
                     paraloc^.size:=int_cgsize(paralen);
                     paraloc^.size:=int_cgsize(paralen);
+                    paraloc^.def:=get_paraloc_def(paradef,paraloc^.size,paralen,firstparaloc);
                     if (side = callerside) then
                     if (side = callerside) then
                       paraloc^.reference.index:=NR_STACK_POINTER_REG
                       paraloc^.reference.index:=NR_STACK_POINTER_REG
                     else
                     else
@@ -392,6 +405,7 @@ unit cpupara;
                     inc(stack_offset,align(paralen,4));
                     inc(stack_offset,align(paralen,4));
                     paralen := 0;
                     paralen := 0;
                   end;
                   end;
+                firstparaloc:=false;
               end;
               end;
           end;
           end;
          result:=stack_offset;
          result:=stack_offset;
@@ -493,6 +507,7 @@ unit cpupara;
               paraloc:=p.paraloc[callerside].add_location;
               paraloc:=p.paraloc[callerside].add_location;
               paraloc^.loc:=LOC_REGISTER;
               paraloc^.loc:=LOC_REGISTER;
               paraloc^.size:=def_cgsize(p.vardef);
               paraloc^.size:=def_cgsize(p.vardef);
+              paraloc^.def:=p.vardef;
               { pattern is always uppercase'd }
               { pattern is always uppercase'd }
               if s='D0' then
               if s='D0' then
                 paraloc^.register:=NR_D0
                 paraloc^.register:=NR_D0

+ 43 - 14
compiler/mips/cpupara.pas

@@ -126,16 +126,20 @@ implementation
     procedure TMIPSParaManager.GetIntParaLoc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure TMIPSParaManager.GetIntParaLoc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym: tparavarsym;
+        pdef: tdef;
       begin
       begin
         if nr<1 then
         if nr<1 then
           InternalError(2002100806);
           InternalError(2002100806);
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
+        psym:=tparavarsym(pd.paras[nr-1]);
+        pdef:=psym.vardef;
+        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+          pdef:=getpointerdef(pdef);
         cgpara.reset;
         cgpara.reset;
-        cgpara.size:=def_cgsize(def);
+        cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.alignment:=std_param_align;
         cgpara.alignment:=std_param_align;
-        cgpara.def:=def;
+        cgpara.def:=pdef;
         paraloc:=cgpara.add_location;
         paraloc:=cgpara.add_location;
         with paraloc^ do
         with paraloc^ do
           begin
           begin
@@ -154,7 +158,8 @@ implementation
                 reference.index:=NR_STACK_POINTER_REG;
                 reference.index:=NR_STACK_POINTER_REG;
                 reference.offset:=nr*mips_sizeof_register_param;
                 reference.offset:=nr*mips_sizeof_register_param;
               end;
               end;
-            size:=OS_INT;
+            size:=def_cgsize(pdef);
+            def:=pdef;
           end;
           end;
       end;
       end;
 
 
@@ -225,6 +230,7 @@ implementation
             if retcgsize=OS_F64 then
             if retcgsize=OS_F64 then
               setsubreg(paraloc^.register,R_SUBFD);
               setsubreg(paraloc^.register,R_SUBFD);
             paraloc^.size:=retcgsize;
             paraloc^.size:=retcgsize;
+            paraloc^.def:=result.def;
           end
           end
         else
         else
          { Return in register }
          { Return in register }
@@ -239,6 +245,7 @@ implementation
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
                { high }
                { high }
                paraloc:=result.add_location;
                paraloc:=result.add_location;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.loc:=LOC_REGISTER;
@@ -247,12 +254,14 @@ implementation
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
              end
              end
             else
             else
 {$endif cpu64bitalu}
 {$endif cpu64bitalu}
              begin
              begin
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.size:=retcgsize;
                paraloc^.size:=retcgsize;
+               paraloc^.def:=result.def;
                if side=callerside then
                if side=callerside then
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
                else
@@ -269,11 +278,13 @@ implementation
         hp           : tparavarsym;
         hp           : tparavarsym;
         paracgsize   : tcgsize;
         paracgsize   : tcgsize;
         paralen      : longint;
         paralen      : longint;
-    paradef      : tdef;
-    fpparareg    : integer;
-    reg           : tsuperregister;
-    alignment     : longint;
-    tmp          : longint;
+        locdef       : tdef;
+        paradef      : tdef;
+        fpparareg    : integer;
+        reg          : tsuperregister;
+        alignment    : longint;
+        tmp          : longint;
+        firstparaloc : boolean;
       begin
       begin
         fpparareg := 0;
         fpparareg := 0;
         for i:=0 to paras.count-1 do
         for i:=0 to paras.count-1 do
@@ -290,6 +301,7 @@ implementation
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_R0;
                 paraloc^.register:=NR_R0;
                 paraloc^.size:=OS_ADDR;
                 paraloc^.size:=OS_ADDR;
+                paraloc^.def:=voidpointertype;
                 break;
                 break;
               end;
               end;
 
 
@@ -321,6 +333,7 @@ implementation
             //writeln('para: ',hp.Name,' typ=',hp.vardef.typ,' paracgsize=',paracgsize,' align=',hp.vardef.alignment);
             //writeln('para: ',hp.Name,' typ=',hp.vardef.typ,' paracgsize=',paracgsize,' align=',hp.vardef.alignment);
             hp.paraloc[side].reset;
             hp.paraloc[side].reset;
             hp.paraloc[side].Alignment:=alignment;
             hp.paraloc[side].Alignment:=alignment;
+            locdef:=paradef;
             if (paracgsize=OS_NO) or
             if (paracgsize=OS_NO) or
               { Ordinals on caller side must be promoted to machine word }
               { Ordinals on caller side must be promoted to machine word }
               ((target_info.endian=endian_big) and     // applies to little-endian too?
               ((target_info.endian=endian_big) and     // applies to little-endian too?
@@ -329,9 +342,15 @@ implementation
               (paralen<tcgsize2size[OS_INT]))then
               (paralen<tcgsize2size[OS_INT]))then
               begin
               begin
                 if is_signed(paradef) then
                 if is_signed(paradef) then
-                  paracgsize:=OS_S32
+                  begin
+                    paracgsize:=OS_S32;
+                    locdef:=s32inttype;
+                  end
                 else
                 else
-                  paracgsize:=OS_32;
+                  begin
+                    paracgsize:=OS_32;
+                    locdef:=u32inttype;
+                  end;
                 paralen:=align(paralen,4);
                 paralen:=align(paralen,4);
               end
               end
             else
             else
@@ -363,6 +382,7 @@ implementation
             if (not(paracgsize in [OS_F32, OS_F64])) or (fpparareg = 2) then
             if (not(paracgsize in [OS_F32, OS_F64])) or (fpparareg = 2) then
               can_use_float := false;
               can_use_float := false;
 
 
+            firstparaloc:=true;
             while paralen>0 do
             while paralen>0 do
               begin
               begin
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc:=hp.paraloc[side].add_location;
@@ -370,9 +390,15 @@ implementation
                 if (paracgsize in [OS_64,OS_S64]) or
                 if (paracgsize in [OS_64,OS_S64]) or
                    ((paracgsize in [OS_F32,OS_F64]) and
                    ((paracgsize in [OS_F32,OS_F64]) and
                      not(can_use_float)) then
                      not(can_use_float)) then
-                  paraloc^.size:=OS_32
+                  begin
+                    paraloc^.size:=OS_32;
+                    paraloc^.def:=u32inttype;
+                  end
                 else
                 else
-                  paraloc^.size:=paracgsize;
+                  begin
+                    paraloc^.size:=paracgsize;
+                    paraloc^.def:=locdef;
+                  end;
 
 
                 { ret in param? }
                 { ret in param? }
                 if (vo_is_funcret in hp.varoptions) and
                 if (vo_is_funcret in hp.varoptions) and
@@ -427,6 +453,7 @@ implementation
                          begin
                          begin
                            paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
                            paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
                            paraloc^.size := OS_INT;
                            paraloc^.size := OS_INT;
+                           paraloc^.def := osuinttype;
                          end;
                          end;
                        inc(intparareg);
                        inc(intparareg);
                        inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
                        inc(intparasize,align(tcgsize2size[paraloc^.size],mips_sizeof_register_param));
@@ -436,6 +463,7 @@ implementation
                   begin
                   begin
                     paraloc^.loc:=LOC_REFERENCE;
                     paraloc^.loc:=LOC_REFERENCE;
                     paraloc^.size:=int_cgsize(paralen);
                     paraloc^.size:=int_cgsize(paralen);
+                    paraloc^.def:=get_paraloc_def(locdef,paraloc^.size,paralen,firstparaloc);
 
 
                     if side=callerside then
                     if side=callerside then
                       begin
                       begin
@@ -463,6 +491,7 @@ implementation
                     paralen:=0;
                     paralen:=0;
                   end;
                   end;
                 dec(paralen,tcgsize2size[paraloc^.size]);
                 dec(paralen,tcgsize2size[paraloc^.size]);
+                firstparaloc:=false;
               end;
               end;
           end;
           end;
         { O32 ABI reqires at least 16 bytes }
         { O32 ABI reqires at least 16 bytes }

+ 1 - 0
compiler/parabase.pas

@@ -39,6 +39,7 @@ unit parabase;
        TCGParaLocation = record
        TCGParaLocation = record
          Next : PCGParaLocation;
          Next : PCGParaLocation;
          Size : TCGSize; { size of this location }
          Size : TCGSize; { size of this location }
+         Def  : tdef;
          Loc  : TCGLoc;
          Loc  : TCGLoc;
          case TCGLoc of
          case TCGLoc of
            LOC_REFERENCE : (reference : TCGParaReference);
            LOC_REFERENCE : (reference : TCGParaReference);

+ 21 - 0
compiler/paramgr.pas

@@ -149,6 +149,11 @@ unit paramgr;
             itself as well; parameter retinparam is only valid if function
             itself as well; parameter retinparam is only valid if function
             returns true }
             returns true }
           function handle_common_ret_in_param(def:tdef;pd:tabstractprocdef;out retinparam:boolean):boolean;
           function handle_common_ret_in_param(def:tdef;pd:tabstractprocdef;out retinparam:boolean):boolean;
+
+          { returns the def to use for a tparalocation part of a cgpara for paradef,
+            for which the tcgsize is locsize and the integer length is restlen.
+            fullsize is true if restlen equals the full paradef size }
+          function get_paraloc_def(paradef: tdef; paracgsize: tcgsize; restlen: aint; fullsize: boolean): tdef;
        end;
        end;
 
 
 
 
@@ -403,6 +408,7 @@ implementation
               len:=tcgsize2size[paraloc^.size];
               len:=tcgsize2size[paraloc^.size];
             newparaloc:=cgpara.add_location;
             newparaloc:=cgpara.add_location;
             newparaloc^.size:=paraloc^.size;
             newparaloc^.size:=paraloc^.size;
+            newparaloc^.def:=paraloc^.def;
             newparaloc^.shiftval:=paraloc^.shiftval;
             newparaloc^.shiftval:=paraloc^.shiftval;
             { $warning maybe release this optimization for all targets?  }
             { $warning maybe release this optimization for all targets?  }
             { released for all CPUs:
             { released for all CPUs:
@@ -543,6 +549,7 @@ implementation
             retloc.size:=OS_NO;
             retloc.size:=OS_NO;
             retcgsize:=OS_NO;
             retcgsize:=OS_NO;
             retloc.intsize:=0;
             retloc.intsize:=0;
+            paraloc^.def:=retloc.def;
             paraloc^.size:=OS_NO;
             paraloc^.size:=OS_NO;
             paraloc^.loc:=LOC_VOID;
             paraloc^.loc:=LOC_VOID;
             exit;
             exit;
@@ -565,6 +572,7 @@ implementation
             paraloc:=retloc.add_location;
             paraloc:=retloc.add_location;
             paraloc^.loc:=LOC_REFERENCE;
             paraloc^.loc:=LOC_REFERENCE;
             paraloc^.size:=retcgsize;
             paraloc^.size:=retcgsize;
+            paraloc^.def:=retloc.def;
             exit;
             exit;
           end;
           end;
         result:=false;
         result:=false;
@@ -602,6 +610,19 @@ implementation
       end;
       end;
 
 
 
 
+    function tparamanager.get_paraloc_def(paradef: tdef; paracgsize: tcgsize; restlen: aint; fullsize: boolean): tdef;
+      begin
+        if fullsize then
+          result:=paradef
+        { no support for 128 bit ints -> tcgsize2orddef can't handle
+          OS_(S)128 }
+        else if not(paracgsize in [OS_NO,OS_128,OS_S128]) then
+          result:=cgsize_orddef(paracgsize)
+        else
+          result:=getarraydef(u8inttype,restlen);
+      end;
+
+
     procedure tparamanager.getintparaloc(pd: tabstractprocdef; nr : longint; var cgpara: tcgpara);
     procedure tparamanager.getintparaloc(pd: tabstractprocdef; nr : longint; var cgpara: tcgpara);
       begin
       begin
         if (nr<1) or (nr>pd.paras.count) then
         if (nr<1) or (nr>pd.paras.count) then

+ 63 - 14
compiler/powerpc/cpupara.pas

@@ -80,18 +80,23 @@ unit cpupara;
     procedure tppcparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure tppcparamanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym : tparavarsym;
+        pdef : tdef;
       begin
       begin
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
+        psym:=tparavarsym(pd.paras[nr-1]);
+        pdef:=psym.vardef;
+        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+          pdef:=getpointerdef(pdef);
         cgpara.reset;
         cgpara.reset;
-        cgpara.size:=def_cgsize(def);
+        cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.alignment:=get_para_align(pd.proccalloption);
         cgpara.alignment:=get_para_align(pd.proccalloption);
-        cgpara.def:=def;
+        cgpara.def:=pdef;
         paraloc:=cgpara.add_location;
         paraloc:=cgpara.add_location;
         with paraloc^ do
         with paraloc^ do
          begin
          begin
-           size:=OS_INT;
+           size:=def_cgsize(pdef);
+           def:=pdef;
            if (nr<=8) then
            if (nr<=8) then
              begin
              begin
                if nr=0 then
                if nr=0 then
@@ -262,6 +267,7 @@ unit cpupara;
             paraloc^.loc:=LOC_FPUREGISTER;
             paraloc^.loc:=LOC_FPUREGISTER;
             paraloc^.register:=NR_FPU_RESULT_REG;
             paraloc^.register:=NR_FPU_RESULT_REG;
             paraloc^.size:=retcgsize;
             paraloc^.size:=retcgsize;
+            paraloc^.def:=result.def;
           end
           end
         else
         else
          { Return in register }
          { Return in register }
@@ -275,6 +281,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
                { high 32bits }
                { high 32bits }
                paraloc:=result.add_location;
                paraloc:=result.add_location;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.loc:=LOC_REGISTER;
@@ -283,6 +290,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
              end
              end
             else
             else
              begin
              begin
@@ -292,6 +300,7 @@ unit cpupara;
                else
                else
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
                paraloc^.size:=retcgsize;
                paraloc^.size:=retcgsize;
+               paraloc^.def:=result.def;
              end;
              end;
           end;
           end;
       end;
       end;
@@ -318,6 +327,7 @@ unit cpupara;
          stack_offset: longint;
          stack_offset: longint;
          paralen: aint;
          paralen: aint;
          nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
          nextintreg,nextfloatreg,nextmmreg, maxfpureg : tsuperregister;
+         locdef,
          paradef : tdef;
          paradef : tdef;
          paraloc : pcgparalocation;
          paraloc : pcgparalocation;
          i  : integer;
          i  : integer;
@@ -325,6 +335,7 @@ unit cpupara;
          loc : tcgloc;
          loc : tcgloc;
          paracgsize: tcgsize;
          paracgsize: tcgsize;
          sym: tfieldvarsym;
          sym: tfieldvarsym;
+         firstparaloc: boolean;
 
 
       begin
       begin
 {$ifdef extdebug}
 {$ifdef extdebug}
@@ -366,6 +377,7 @@ unit cpupara;
                   paraloc^.loc := LOC_REGISTER;
                   paraloc^.loc := LOC_REGISTER;
                   paraloc^.register := NR_R0;
                   paraloc^.register := NR_R0;
                   paraloc^.size := OS_ADDR;
                   paraloc^.size := OS_ADDR;
+                  paraloc^.def:=voidpointertype;
                   break;
                   break;
                 end;
                 end;
 
 
@@ -420,10 +432,16 @@ unit cpupara;
                  (paradef.typ = floatdef) then
                  (paradef.typ = floatdef) then
                 begin
                 begin
                   loc := LOC_REGISTER;
                   loc := LOC_REGISTER;
-                  if paracgsize = OS_F64 then
-                    paracgsize := OS_64
+                  if paracgsize=OS_F64 then
+                    begin
+                      paracgsize:=OS_64;
+                      paradef:=u64inttype;
+                    end
                   else
                   else
-                    paracgsize := OS_32;
+                    begin
+                      paracgsize:=OS_32;
+                      paradef:=u32inttype;
+                    end;
                 end;
                 end;
 
 
               hp.paraloc[side].alignment:=std_param_align;
               hp.paraloc[side].alignment:=std_param_align;
@@ -444,6 +462,8 @@ unit cpupara;
                   end
                   end
                 else
                 else
                   internalerror(2005011310);
                   internalerror(2005011310);
+              locdef:=paradef;
+              firstparaloc:=true;
               { can become < 0 for e.g. 3-byte records }
               { can become < 0 for e.g. 3-byte records }
               while (paralen > 0) do
               while (paralen > 0) do
                 begin
                 begin
@@ -457,12 +477,21 @@ unit cpupara;
                     begin
                     begin
                       paraloc^.loc := loc;
                       paraloc^.loc := loc;
                       { make sure we don't lose whether or not the type is signed }
                       { make sure we don't lose whether or not the type is signed }
-                      if (paradef.typ <> orddef) then
-                        paracgsize := int_cgsize(paralen);
+                      if (paradef.typ<>orddef) then
+                        begin
+                          paracgsize:=int_cgsize(paralen);
+                          locdef:=get_paraloc_def(paradef,paracgsize,paralen,firstparaloc);
+                        end;
                       if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
                       if (paracgsize in [OS_NO,OS_64,OS_S64,OS_128,OS_S128]) then
-                        paraloc^.size := OS_INT
+                        begin
+                          paraloc^.size:=OS_INT;
+                          paraloc^.def:=u32inttype;
+                        end
                       else
                       else
-                        paraloc^.size := paracgsize;
+                        begin
+                          paraloc^.size:=paracgsize;
+                          paraloc^.def:=locdef;
+                        end;
                       { aix requires that record data stored in parameter
                       { aix requires that record data stored in parameter
                         registers is left-aligned }
                         registers is left-aligned }
                       if (target_info.system in systems_aix) and
                       if (target_info.system in systems_aix) and
@@ -471,6 +500,7 @@ unit cpupara;
                         begin
                         begin
                           paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
                           paraloc^.shiftval := (sizeof(aint)-tcgsize2size[paraloc^.size])*(-8);
                           paraloc^.size := OS_INT;
                           paraloc^.size := OS_INT;
+                          paraloc^.def := u32inttype;
                         end;
                         end;
                       paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
                       paraloc^.register:=newreg(R_INTREGISTER,nextintreg,R_SUBNONE);
                       inc(nextintreg);
                       inc(nextintreg);
@@ -483,6 +513,7 @@ unit cpupara;
                     begin
                     begin
                       paraloc^.loc:=loc;
                       paraloc^.loc:=loc;
                       paraloc^.size := paracgsize;
                       paraloc^.size := paracgsize;
+                      paraloc^.def := paradef;
                       paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
                       paraloc^.register:=newreg(R_FPUREGISTER,nextfloatreg,R_SUBWHOLE);
                       inc(nextfloatreg);
                       inc(nextfloatreg);
                       dec(paralen,tcgsize2size[paraloc^.size]);
                       dec(paralen,tcgsize2size[paraloc^.size]);
@@ -517,10 +548,24 @@ unit cpupara;
                        paraloc^.loc:=LOC_REFERENCE;
                        paraloc^.loc:=LOC_REFERENCE;
                        case loc of
                        case loc of
                          LOC_FPUREGISTER:
                          LOC_FPUREGISTER:
-                           paraloc^.size:=int_float_cgsize(paralen);
+                           begin
+                             paraloc^.size:=int_float_cgsize(paralen);
+                             case paraloc^.size of
+                               OS_F32: paraloc^.def:=s32floattype;
+                               OS_F64: paraloc^.def:=s64floattype;
+                               else
+                                 internalerror(2013060124);
+                             end;
+                           end;
                          LOC_REGISTER,
                          LOC_REGISTER,
                          LOC_REFERENCE:
                          LOC_REFERENCE:
-                           paraloc^.size:=int_cgsize(paralen);
+                           begin
+                             paraloc^.size:=int_cgsize(paralen);
+                             if paraloc^.size<>OS_NO then
+                               paraloc^.def:=cgsize_orddef(paraloc^.size)
+                             else
+                               paraloc^.def:=getarraydef(u8inttype,paralen);
+                           end;
                          else
                          else
                            internalerror(2006011101);
                            internalerror(2006011101);
                        end;
                        end;
@@ -553,6 +598,7 @@ unit cpupara;
                           end;
                           end;
                        paralen := 0;
                        paralen := 0;
                     end;
                     end;
+                  firstparaloc:=false;
                 end;
                 end;
             end;
             end;
          curintreg:=nextintreg;
          curintreg:=nextintreg;
@@ -595,6 +641,7 @@ unit cpupara;
                 paraloc:=hp.paraloc[callerside].add_location;
                 paraloc:=hp.paraloc[callerside].add_location;
                 paraloc^.loc:=LOC_REFERENCE;
                 paraloc^.loc:=LOC_REFERENCE;
                 paraloc^.size:=def_cgsize(hp.vardef);
                 paraloc^.size:=def_cgsize(hp.vardef);
+                paraloc^.def:=hp.vardef;
                 paraloc^.reference.index:=NR_STACK_POINTER_REG;
                 paraloc^.reference.index:=NR_STACK_POINTER_REG;
                 l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
                 l:=push_size(hp.varspez,hp.vardef,p.proccalloption);
                 paraloc^.reference.offset:=parasize;
                 paraloc^.reference.offset:=parasize;
@@ -623,6 +670,7 @@ unit cpupara;
               paraloc:=p.paraloc[callerside].add_location;
               paraloc:=p.paraloc[callerside].add_location;
               paraloc^.loc:=LOC_REFERENCE;
               paraloc^.loc:=LOC_REFERENCE;
               paraloc^.size:=paracgsize;
               paraloc^.size:=paracgsize;
+              paraloc^.def:=p.vardef;
               paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
               paraloc^.reference.index:=newreg(R_INTREGISTER,RS_R2,R_SUBWHOLE);
               { pattern is always uppercase'd }
               { pattern is always uppercase'd }
               if s='D0' then
               if s='D0' then
@@ -667,6 +715,7 @@ unit cpupara;
                 begin
                 begin
                   paraloc^.loc:=LOC_REGISTER;
                   paraloc^.loc:=LOC_REGISTER;
                   paraloc^.size:=OS_ADDR;
                   paraloc^.size:=OS_ADDR;
+                  paraloc^.def:=voidpointertype;
                   paraloc^.register:=NR_R12;
                   paraloc^.register:=NR_R12;
                 end
                 end
               else
               else

+ 46 - 10
compiler/powerpc64/cpupara.pas

@@ -80,17 +80,22 @@ end;
 procedure tppcparamanager.getintparaloc(pd : tabstractprocdef; nr: longint; var cgpara: tcgpara);
 procedure tppcparamanager.getintparaloc(pd : tabstractprocdef; nr: longint; var cgpara: tcgpara);
 var
 var
   paraloc: pcgparalocation;
   paraloc: pcgparalocation;
-  def: tdef;
+  psym: tparavarsym;
+  pdef: tdef;
 begin
 begin
-  def:=tparavarsym(pd.paras[nr-1]).vardef;
+  psym:=tparavarsym(pd.paras[nr-1]);
+  pdef:=psym.vardef;
+  if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+    pdef:=getpointerdef(pdef);
   cgpara.reset;
   cgpara.reset;
-  cgpara.size := def_cgsize(def);
+  cgpara.size := def_cgsize(pdef);
   cgpara.intsize := tcgsize2size[cgpara.size];
   cgpara.intsize := tcgsize2size[cgpara.size];
   cgpara.alignment := get_para_align(pd.proccalloption);
   cgpara.alignment := get_para_align(pd.proccalloption);
-  cgpara.def:=def;
+  cgpara.def:=pdef;
   paraloc := cgpara.add_location;
   paraloc := cgpara.add_location;
   with paraloc^ do begin
   with paraloc^ do begin
-    size := OS_INT;
+    size := def_cgsize(pdef);
+    def := pdef;
     if (nr <= 8) then begin
     if (nr <= 8) then begin
       if (nr = 0) then
       if (nr = 0) then
         internalerror(200309271);
         internalerror(200309271);
@@ -219,6 +224,7 @@ begin
       paraloc^.loc:=LOC_FPUREGISTER;
       paraloc^.loc:=LOC_FPUREGISTER;
       paraloc^.register:=NR_FPU_RESULT_REG;
       paraloc^.register:=NR_FPU_RESULT_REG;
       paraloc^.size:=retcgsize;
       paraloc^.size:=retcgsize;
+      paraloc^.def:=result.def;
     end
     end
   else
   else
    { Return in register }
    { Return in register }
@@ -229,6 +235,7 @@ begin
        else
        else
          paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
          paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize));
        paraloc^.size:=retcgsize;
        paraloc^.size:=retcgsize;
+       paraloc^.def:=result.def;
      end;
      end;
 end;
 end;
 
 
@@ -255,6 +262,7 @@ var
   stack_offset: longint;
   stack_offset: longint;
   paralen: aint;
   paralen: aint;
   nextintreg, nextfloatreg, nextmmreg : tsuperregister;
   nextintreg, nextfloatreg, nextmmreg : tsuperregister;
+  locdef,
   paradef: tdef;
   paradef: tdef;
   paraloc: pcgparalocation;
   paraloc: pcgparalocation;
   i: integer;
   i: integer;
@@ -263,6 +271,7 @@ var
   paracgsize: tcgsize;
   paracgsize: tcgsize;
 
 
   parashift : byte;
   parashift : byte;
+  firstparaloc,
   adjusttail: boolean;
   adjusttail: boolean;
 
 
 begin
 begin
@@ -295,6 +304,7 @@ begin
       paraloc^.loc := LOC_REGISTER;
       paraloc^.loc := LOC_REGISTER;
       paraloc^.register := NR_R0;
       paraloc^.register := NR_R0;
       paraloc^.size := OS_ADDR;
       paraloc^.size := OS_ADDR;
+      paraloc^.def := voidpointertype;
       break;
       break;
     end;
     end;
 
 
@@ -359,6 +369,8 @@ begin
       end else
       end else
         internalerror(2005011310);
         internalerror(2005011310);
     adjusttail:=paralen>8;
     adjusttail:=paralen>8;
+    locdef:=paradef;
+    firstparaloc:=true;
     { can become < 0 for e.g. 3-byte records }
     { can become < 0 for e.g. 3-byte records }
     while (paralen > 0) do begin
     while (paralen > 0) do begin
       paraloc := hp.paraloc[side].add_location;
       paraloc := hp.paraloc[side].add_location;
@@ -373,7 +385,10 @@ begin
 
 
         { make sure we don't lose whether or not the type is signed }
         { make sure we don't lose whether or not the type is signed }
         if (paracgsize <> OS_NO) and (paradef.typ <> orddef) then
         if (paracgsize <> OS_NO) and (paradef.typ <> orddef) then
-          paracgsize := int_cgsize(paralen);
+          begin
+            paracgsize := int_cgsize(paralen);
+            locdef:=get_paraloc_def(paradef,paracgsize,paralen,firstparaloc);
+          end;
 
 
         { aix requires that record data (including partial data) stored in
         { aix requires that record data (including partial data) stored in
           parameter registers is left-aligned. Other targets only do this if
           parameter registers is left-aligned. Other targets only do this if
@@ -385,11 +400,18 @@ begin
           begin
           begin
             paraloc^.shiftval := (sizeof(aint)-paralen)*(-8);
             paraloc^.shiftval := (sizeof(aint)-paralen)*(-8);
             paraloc^.size := OS_INT;
             paraloc^.size := OS_INT;
+            paraloc^.def := u64inttype;
           end
           end
         else if (paracgsize in [OS_NO,OS_128,OS_S128]) then
         else if (paracgsize in [OS_NO,OS_128,OS_S128]) then
-          paraloc^.size := OS_INT
+          begin
+            paraloc^.size := OS_INT;
+            paraloc^.def := osuinttype;
+          end
         else
         else
-          paraloc^.size := paracgsize;
+          begin
+            paraloc^.size := paracgsize;
+            paraloc^.def := locdef;
+          end;
 
 
         paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
         paraloc^.register := newreg(R_INTREGISTER, nextintreg, R_SUBNONE);
         inc(nextintreg);
         inc(nextintreg);
@@ -400,6 +422,7 @@ begin
         (nextfloatreg <= RS_F13) then begin
         (nextfloatreg <= RS_F13) then begin
         paraloc^.loc := loc;
         paraloc^.loc := loc;
         paraloc^.size := paracgsize;
         paraloc^.size := paracgsize;
+        paraloc^.def := locdef;
         paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
         paraloc^.register := newreg(R_FPUREGISTER, nextfloatreg, R_SUBWHOLE);
         { the PPC64 ABI says that the GPR index is increased for every parameter, no matter
         { the PPC64 ABI says that the GPR index is increased for every parameter, no matter
         which type it is stored in }
         which type it is stored in }
@@ -417,10 +440,21 @@ begin
         paraloc^.loc := LOC_REFERENCE;
         paraloc^.loc := LOC_REFERENCE;
         case loc of
         case loc of
           LOC_FPUREGISTER:
           LOC_FPUREGISTER:
-            paraloc^.size:=int_float_cgsize(paralen);
+            begin
+              paraloc^.size:=int_float_cgsize(paralen);
+              case paraloc^.size of
+                OS_F32: paraloc^.def:=s32floattype;
+                OS_F64: paraloc^.def:=s64floattype;
+                else
+                  internalerror(2013060122);
+              end;
+            end;
           LOC_REGISTER,
           LOC_REGISTER,
           LOC_REFERENCE:
           LOC_REFERENCE:
-            paraloc^.size:=int_cgsize(paralen);
+            begin
+              paraloc^.size:=int_cgsize(paralen);
+              paraloc^.def:=get_paraloc_def(paradef,paraloc^.size,paralen,firstparaloc);
+            end;
           else
           else
             internalerror(2006011101);
             internalerror(2006011101);
         end;
         end;
@@ -440,6 +474,7 @@ begin
         inc(stack_offset, align(paralen, 8));
         inc(stack_offset, align(paralen, 8));
         paralen := 0;
         paralen := 0;
       end;
       end;
+      firstparaloc:=false;
     end;
     end;
   end;
   end;
 
 
@@ -480,6 +515,7 @@ begin
       paraloc := hp.paraloc[callerside].add_location;
       paraloc := hp.paraloc[callerside].add_location;
       paraloc^.loc := LOC_REFERENCE;
       paraloc^.loc := LOC_REFERENCE;
       paraloc^.size := def_cgsize(hp.vardef);
       paraloc^.size := def_cgsize(hp.vardef);
+      paraloc^.def := hp.vardef;
       paraloc^.reference.index := NR_STACK_POINTER_REG;
       paraloc^.reference.index := NR_STACK_POINTER_REG;
       l := push_size(hp.varspez, hp.vardef, p.proccalloption);
       l := push_size(hp.varspez, hp.vardef, p.proccalloption);
       paraloc^.reference.offset := parasize;
       paraloc^.reference.offset := parasize;

+ 23 - 7
compiler/sparc/cpupara.pas

@@ -77,16 +77,20 @@ implementation
     procedure TSparcParaManager.GetIntParaLoc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure TSparcParaManager.GetIntParaLoc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym: tparavarsym;
+        pdef: tdef;
       begin
       begin
         if nr<1 then
         if nr<1 then
           InternalError(2002100806);
           InternalError(2002100806);
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
+        psym:=tparavarsym(pd.paras[nr-1]);
+        pdef:=psym.vardef;
+        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+          pdef:=getpointerdef(pdef);
         cgpara.reset;
         cgpara.reset;
-        cgpara.size:=def_cgsize(def);
+        cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.alignment:=std_param_align;
         cgpara.alignment:=std_param_align;
-        cgpara.def:=def;
+        cgpara.def:=pdef;
         paraloc:=cgpara.add_location;
         paraloc:=cgpara.add_location;
         with paraloc^ do
         with paraloc^ do
           begin
           begin
@@ -104,7 +108,8 @@ implementation
                 reference.index:=NR_STACK_POINTER_REG;
                 reference.index:=NR_STACK_POINTER_REG;
                 reference.offset:=92+(nr-6)*4;
                 reference.offset:=92+(nr-6)*4;
               end;
               end;
-            size:=OS_INT;
+            size:=def_cgsize(pdef);
+            def:=pdef;
           end;
           end;
       end;
       end;
 
 
@@ -158,6 +163,7 @@ implementation
             if retcgsize=OS_F64 then
             if retcgsize=OS_F64 then
               setsubreg(paraloc^.register,R_SUBFD);
               setsubreg(paraloc^.register,R_SUBFD);
             paraloc^.size:=retcgsize;
             paraloc^.size:=retcgsize;
+            paraloc^.def:=result.def;
           end
           end
         else
         else
          { Return in register }
          { Return in register }
@@ -172,6 +178,7 @@ implementation
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_HIGH_REG;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
                { low }
                { low }
                paraloc:=result.add_location;
                paraloc:=result.add_location;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.loc:=LOC_REGISTER;
@@ -180,12 +187,14 @@ implementation
                else
                else
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                  paraloc^.register:=NR_FUNCTION_RETURN64_LOW_REG;
                paraloc^.size:=OS_32;
                paraloc^.size:=OS_32;
+               paraloc^.def:=u32inttype;
              end
              end
             else
             else
 {$endif not cpu64bitaddr}
 {$endif not cpu64bitaddr}
              begin
              begin
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.loc:=LOC_REGISTER;
                paraloc^.size:=retcgsize;
                paraloc^.size:=retcgsize;
+               paraloc^.def:=result.def;
                if (side=callerside) then
                if (side=callerside) then
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                  paraloc^.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize))
                else
                else
@@ -224,6 +233,7 @@ implementation
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.loc:=LOC_REGISTER;
                 paraloc^.register:=NR_G0;
                 paraloc^.register:=NR_G0;
                 paraloc^.size:=OS_ADDR;
                 paraloc^.size:=OS_ADDR;
+                paraloc^.def:=voidpointertype;
                 break;
                 break;
               end;
               end;
 
 
@@ -257,9 +267,15 @@ implementation
                 { Floats are passed in int registers,
                 { Floats are passed in int registers,
                   We can allocate at maximum 32 bits per register }
                   We can allocate at maximum 32 bits per register }
                 if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
                 if paracgsize in [OS_64,OS_S64,OS_F32,OS_F64] then
-                  paraloc^.size:=OS_32
+                  begin
+                    paraloc^.size:=OS_32;
+                    paraloc^.def:=u32inttype;
+                  end
                 else
                 else
-                  paraloc^.size:=paracgsize;
+                  begin
+                    paraloc^.size:=paracgsize;
+                    paraloc^.def:=paradef;
+                  end;
                 { ret in param? }
                 { ret in param? }
                 if vo_is_funcret in hp.varoptions then
                 if vo_is_funcret in hp.varoptions then
                   begin
                   begin

+ 286 - 126
compiler/x86_64/cpupara.pas

@@ -99,7 +99,7 @@ unit cpupara;
       MAX_PARA_CLASSES = 4;
       MAX_PARA_CLASSES = 4;
 
 
     type
     type
-      tx64paraclass = (
+      tx64paraclasstype = (
         X86_64_NO_CLASS,
         X86_64_NO_CLASS,
         X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS,
         X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS,
         X86_64_SSE_CLASS,X86_64_SSESF_CLASS,X86_64_SSEDF_CLASS,X86_64_SSEUP_CLASS,
         X86_64_SSE_CLASS,X86_64_SSESF_CLASS,X86_64_SSEDF_CLASS,X86_64_SSEUP_CLASS,
@@ -107,6 +107,12 @@ unit cpupara;
         X86_64_COMPLEX_X87_CLASS,
         X86_64_COMPLEX_X87_CLASS,
         X86_64_MEMORY_CLASS
         X86_64_MEMORY_CLASS
       );
       );
+
+      tx64paraclass = record
+        def: tdef;
+        typ: tx64paraclasstype;
+      end;
+
       tx64paraclasses = array[0..MAX_PARA_CLASSES-1] of tx64paraclass;
       tx64paraclasses = array[0..MAX_PARA_CLASSES-1] of tx64paraclass;
 
 
     { Win64-specific helper }
     { Win64-specific helper }
@@ -120,82 +126,168 @@ unit cpupara;
        of this code is to classify each 8bytes of incoming argument by the register
        of this code is to classify each 8bytes of incoming argument by the register
        class and assign registers accordingly.  *)
        class and assign registers accordingly.  *)
 
 
+
+       function classify_representative_def(def1, def2: tdef): tdef;
+         var
+           def1size, def2size: asizeint;
+         begin
+           if not assigned(def1) then
+             result:=def2
+           else if not assigned(def2) then
+             result:=def1
+           else
+             begin
+               def1size:=def1.size;
+               def2size:=def2.size;
+               if def1size>def2size then
+                 result:=def1
+               else if def2size>def1size then
+                 result:=def2
+               else if def1.alignment>def2.alignment then
+                 result:=def1
+               else
+                 result:=def2;
+             end;
+         end;
+
+       (* Classify the argument of type TYPE and mode MODE.
+          CLASSES will be filled by the register class used to pass each word
+          of the operand.  The number of words is returned.  In case the parameter
+          should be passed in memory, 0 is returned. As a special case for zero
+          sized containers, classes[0] will be NO_CLASS and 1 is returned.
+
+          real_size contains either def.size, or a value derived from
+          def.bitpackedsize and the field offset denoting the number of bytes
+          spanned by a bitpacked field
+
+          See the x86-64 PS ABI for details.
+       *)
+       procedure classify_single_integer_class(def: tdef; size,real_size: aint; var cl: tx64paraclass; byte_offset: aint);
+         begin
+           if (byte_offset=0) and
+              (real_size in [1,2,4,8]) and
+              (not assigned(cl.def) or
+               (def.alignment>=cl.def.alignment)) then
+             cl.def:=def;
+           if size<=4 then
+             begin
+               cl.typ:=X86_64_INTEGERSI_CLASS;
+               if not assigned(cl.def) or
+                  (cl.def.size<size) then
+                 begin
+                   case size of
+                     1: cl.def:=u8inttype;
+                     2: cl.def:=u16inttype;
+                     3,4: cl.def:=u32inttype;
+                   end;
+                 end;
+             end
+           else
+             begin
+               cl.typ:=X86_64_INTEGER_CLASS;
+               if not assigned(cl.def) or
+                  (cl.def.size<size) then
+                 cl.def:=u64inttype;
+             end;
+         end;
+
+
+       function classify_as_integer_argument(def: tdef; real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint;
+         var
+           size: aint;
+         begin
+           size:=byte_offset+real_size;
+           classify_single_integer_class(def,size,real_size,classes[0],byte_offset);
+           if size<=8 then
+             result:=1
+           else
+             begin
+               classify_single_integer_class(def,size-8,real_size,classes[1],byte_offset-8);
+               if size>16 then
+                 internalerror(2010021401);
+               result:=2;
+             end
+         end;
+
+
     (* Return the union class of CLASS1 and CLASS2.
     (* Return the union class of CLASS1 and CLASS2.
        See the x86-64 PS ABI for details.  *)
        See the x86-64 PS ABI for details.  *)
 
 
     function merge_classes(class1, class2: tx64paraclass): tx64paraclass;
     function merge_classes(class1, class2: tx64paraclass): tx64paraclass;
       begin
       begin
         (* Rule #1: If both classes are equal, this is the resulting class.  *)
         (* Rule #1: If both classes are equal, this is the resulting class.  *)
-        if (class1=class2) then
-          exit(class1);
+        if (class1.typ=class2.typ) then
+          begin
+            result.typ:=class1.typ;
+            result.def:=classify_representative_def(class1.def,class2.def);
+            exit;
+          end;
 
 
         (* Rule #2: If one of the classes is NO_CLASS, the resulting class is
         (* Rule #2: If one of the classes is NO_CLASS, the resulting class is
            the other class.  *)
            the other class.  *)
-        if (class1=X86_64_NO_CLASS) then
+        if (class1.typ=X86_64_NO_CLASS) then
           exit(class2);
           exit(class2);
-        if (class2=X86_64_NO_CLASS) then
+        if (class2.typ=X86_64_NO_CLASS) then
           exit(class1);
           exit(class1);
 
 
         (* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  *)
         (* Rule #3: If one of the classes is MEMORY, the result is MEMORY.  *)
-        if (class1=X86_64_MEMORY_CLASS) or
-           (class2=X86_64_MEMORY_CLASS) then
-          exit(X86_64_MEMORY_CLASS);
+        if (class1.typ=X86_64_MEMORY_CLASS) then
+          exit(class1)
+        else if (class2.typ=X86_64_MEMORY_CLASS) then
+          exit(class2);
 
 
         (* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  *)
         (* Rule #4: If one of the classes is INTEGER, the result is INTEGER.  *)
         { 32 bit }
         { 32 bit }
-        if ((class1=X86_64_INTEGERSI_CLASS) and
-            (class2=X86_64_SSESF_CLASS)) or
-           ((class2=X86_64_INTEGERSI_CLASS) and
-            (class1=X86_64_SSESF_CLASS)) then
-          exit(X86_64_INTEGERSI_CLASS);
+        if ((class1.typ=X86_64_INTEGERSI_CLASS) and
+            (class2.typ=X86_64_SSESF_CLASS)) then
+          exit(class1)
+        else if ((class2.typ=X86_64_INTEGERSI_CLASS) and
+            (class1.typ=X86_64_SSESF_CLASS)) then
+          exit(class2);
         { 64 bit }
         { 64 bit }
-        if (class1 in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) or
-           (class2 in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) then
-          exit(X86_64_INTEGER_CLASS);
+        if (class1.typ in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) then
+          begin
+            result:=class1;
+            if result.def.size<8 then
+              begin
+                result.typ:=X86_64_INTEGER_CLASS;
+                result.def:=s64inttype;
+              end;
+            exit
+          end
+        else if (class2.typ in [X86_64_INTEGER_CLASS,X86_64_INTEGERSI_CLASS]) then
+          begin
+            result:=class2;
+            if result.def.size<8 then
+              begin
+                result.typ:=X86_64_INTEGER_CLASS;
+                result.def:=s64inttype;
+              end;
+            exit
+          end;
 
 
         (* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
         (* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class,
            MEMORY is used.  *)
            MEMORY is used.  *)
-        if (class1 in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) or
-           (class2 in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) then
-          exit(X86_64_MEMORY_CLASS);
+        if (class1.typ in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) then
+          begin
+            result:=class1;
+            result.typ:=X86_64_MEMORY_CLASS;
+            exit;
+          end
+        else if (class2.typ in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS]) then
+          begin
+            result:=class2;
+            result.typ:=X86_64_MEMORY_CLASS;
+            exit;
+          end;
 
 
         (* Rule #6: Otherwise class SSE is used.  *)
         (* Rule #6: Otherwise class SSE is used.  *)
-        result:=X86_64_SSE_CLASS;
-      end;
-
-    (* Classify the argument of type TYPE and mode MODE.
-       CLASSES will be filled by the register class used to pass each word
-       of the operand.  The number of words is returned.  In case the parameter
-       should be passed in memory, 0 is returned. As a special case for zero
-       sized containers, classes[0] will be NO_CLASS and 1 is returned.
-
-       real_size contains either def.size, or a value derived from
-       def.bitpackedsize and the field offset denoting the number of bytes
-       spanned by a bitpacked field
-
-       See the x86-64 PS ABI for details.
-    *)
-    function classify_as_integer_argument(real_size: aint; var classes: tx64paraclasses; byte_offset: aint): longint;
-      var
-        size: aint;
-      begin
-        size:=byte_offset+real_size;
-        if size<=4 then
-          classes[0]:=X86_64_INTEGERSI_CLASS
+        if class1.def.size>class2.def.size then
+          result:=class1
         else
         else
-          classes[0]:=X86_64_INTEGER_CLASS;
-        if size<=8 then
-          result:=1
-        else
-          begin
-             if size<=12 then
-               classes[1]:=X86_64_INTEGERSI_CLASS
-             else if (size<=16) then
-               classes[1]:=X86_64_INTEGER_CLASS
-             else
-               internalerror(2010021401);
-            result:=2;
-          end
+          result:=class2;
+        result.typ:=X86_64_SSE_CLASS;
+        result.def:=getarraydef(s32floattype,2)
       end;
       end;
 
 
 
 
@@ -211,7 +303,8 @@ unit cpupara;
           begin
           begin
             if aggregate_in_registers_win64(varspez,def.size) then
             if aggregate_in_registers_win64(varspez,def.size) then
               begin
               begin
-                classes[0]:=X86_64_INTEGER_CLASS;
+                classes[0].typ:=X86_64_INTEGER_CLASS;
+                classes[0].def:=def;
                 result:=1;
                 result:=1;
               end
               end
             else
             else
@@ -231,14 +324,18 @@ unit cpupara;
            signal memory class, so handle it as special case.  *)
            signal memory class, so handle it as special case.  *)
         if (words=0) then
         if (words=0) then
           begin
           begin
-            classes[0]:=X86_64_NO_CLASS;
+            classes[0].typ:=X86_64_NO_CLASS;
+            classes[0].def:=def;
             exit(1);
             exit(1);
           end;
           end;
 
 
         { we'll be merging the classes elements with the subclasses
         { we'll be merging the classes elements with the subclasses
           elements, so initialise them first }
           elements, so initialise them first }
         for i:=low(classes) to high(classes) do
         for i:=low(classes) to high(classes) do
-          classes[i]:=X86_64_NO_CLASS;
+          begin
+            classes[i].typ:=X86_64_NO_CLASS;
+            classes[i].def:=nil;
+          end;
         result:=words;
         result:=words;
       end;
       end;
 
 
@@ -249,6 +346,7 @@ unit cpupara;
         i,
         i,
         pos: longint;
         pos: longint;
       begin
       begin
+        fillchar(subclasses,sizeof(subclasses),0);
         result:=classify_argument(def,varspez,real_size,subclasses,new_byte_offset mod 8);
         result:=classify_argument(def,varspez,real_size,subclasses,new_byte_offset mod 8);
         if (result=0) then
         if (result=0) then
           exit;
           exit;
@@ -274,38 +372,41 @@ unit cpupara;
                X86_64_SSE_CLASS or any other ones aren't
                X86_64_SSE_CLASS or any other ones aren't
                X86_64_SSEUP_CLASS, everything should be passed in
                X86_64_SSEUP_CLASS, everything should be passed in
                memory.  *)
                memory.  *)
-            if (classes[0]<>X86_64_SSE_CLASS) then
+            if (classes[0].typ<>X86_64_SSE_CLASS) then
               exit(0);
               exit(0);
 
 
             for i:=1 to words-1 do
             for i:=1 to words-1 do
-              if (classes[i]<>X86_64_SSEUP_CLASS) then
+              if (classes[i].typ<>X86_64_SSEUP_CLASS) then
                 exit(0);
                 exit(0);
           end;
           end;
 
 
         (* Final merger cleanup.  *)
         (* Final merger cleanup.  *)
         (* The first one must never be X86_64_SSEUP_CLASS or
         (* The first one must never be X86_64_SSEUP_CLASS or
            X86_64_X87UP_CLASS.  *)
            X86_64_X87UP_CLASS.  *)
-        if (classes[0]=X86_64_SSEUP_CLASS) or
-           (classes[0]=X86_64_X87UP_CLASS) then
+        if (classes[0].typ=X86_64_SSEUP_CLASS) or
+           (classes[0].typ=X86_64_X87UP_CLASS) then
           internalerror(2010021402);
           internalerror(2010021402);
         for i:=0 to words-1 do
         for i:=0 to words-1 do
           begin
           begin
             (* If one class is MEMORY, everything should be passed in
             (* If one class is MEMORY, everything should be passed in
                memory.  *)
                memory.  *)
-            if (classes[i]=X86_64_MEMORY_CLASS) then
+            if (classes[i].typ=X86_64_MEMORY_CLASS) then
               exit(0);
               exit(0);
 
 
             (* The X86_64_SSEUP_CLASS should be always preceded by
             (* The X86_64_SSEUP_CLASS should be always preceded by
                X86_64_SSE_CLASS or X86_64_SSEUP_CLASS.  *)
                X86_64_SSE_CLASS or X86_64_SSEUP_CLASS.  *)
-            if (classes[i]=X86_64_SSEUP_CLASS) and
-               (classes[i-1]<>X86_64_SSE_CLASS) and
-               (classes[i-1]<>X86_64_SSEUP_CLASS) then
-              classes[i]:=X86_64_SSE_CLASS;
+            if (classes[i].typ=X86_64_SSEUP_CLASS) and
+               (classes[i-1].typ<>X86_64_SSE_CLASS) and
+               (classes[i-1].typ<>X86_64_SSEUP_CLASS) then
+              begin
+                classes[i].typ:=X86_64_SSE_CLASS;
+                classes[i].def:=getarraydef(s32floattype,2);
+              end;
 
 
             (*  If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
             (*  If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
                 everything should be passed in memory.  *)
                 everything should be passed in memory.  *)
-            if (classes[i]=X86_64_X87UP_CLASS) and
-               (classes[i-1]<>X86_64_X87_CLASS) then
+            if (classes[i].typ=X86_64_X87UP_CLASS) and
+               (classes[i-1].typ<>X86_64_X87_CLASS) then
               exit(0);
               exit(0);
           end;
           end;
 
 
@@ -317,20 +418,32 @@ unit cpupara;
             such locations always up to 64 bits, although this loads/stores
             such locations always up to 64 bits, although this loads/stores
             some superfluous data }
             some superfluous data }
           { 1) the first part is 32 bit while there is still a second part }
           { 1) the first part is 32 bit while there is still a second part }
-          if (classes[1]<>X86_64_NO_CLASS) then
-            case classes[0] of
+          if (classes[1].typ<>X86_64_NO_CLASS) then
+            case classes[0].typ of
               X86_64_INTEGERSI_CLASS:
               X86_64_INTEGERSI_CLASS:
-                classes[0]:=X86_64_INTEGER_CLASS;
+                begin
+                  classes[0].typ:=X86_64_INTEGER_CLASS;
+                  classes[0].def:=s64inttype;
+                end;
               X86_64_SSESF_CLASS:
               X86_64_SSESF_CLASS:
-                classes[0]:=X86_64_SSE_CLASS;
+                begin
+                  classes[0].typ:=X86_64_SSE_CLASS;
+                  classes[0].def:=getarraydef(s32floattype,2);
+                end;
             end;
             end;
           { 2) the second part is 32 bit, but the total size is > 12 bytes }
           { 2) the second part is 32 bit, but the total size is > 12 bytes }
           if (def.size>12) then
           if (def.size>12) then
-            case classes[1] of
+            case classes[1].typ of
               X86_64_INTEGERSI_CLASS:
               X86_64_INTEGERSI_CLASS:
-                classes[1]:=X86_64_INTEGER_CLASS;
+                begin
+                  classes[1].typ:=X86_64_INTEGER_CLASS;
+                  classes[1].def:=s64inttype;
+                end;
               X86_64_SSESF_CLASS:
               X86_64_SSESF_CLASS:
-                classes[1]:=X86_64_SSE_CLASS;
+                begin
+                  classes[1].typ:=X86_64_SSE_CLASS;
+                  classes[1].def:=getarraydef(s32floattype,2);
+                end;
             end;
             end;
 
 
           result:=words;
           result:=words;
@@ -466,44 +579,51 @@ unit cpupara;
           enumdef,
           enumdef,
           pointerdef,
           pointerdef,
           classrefdef:
           classrefdef:
-            result:=classify_as_integer_argument(real_size,classes,byte_offset);
+            result:=classify_as_integer_argument(def,real_size,classes,byte_offset);
           formaldef:
           formaldef:
-            result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset);
+            result:=classify_as_integer_argument(voidpointertype,voidpointertype.size,classes,byte_offset);
           floatdef:
           floatdef:
             begin
             begin
+              classes[0].def:=def;
               case tfloatdef(def).floattype of
               case tfloatdef(def).floattype of
                 s32real:
                 s32real:
                   begin
                   begin
                     if byte_offset=0 then
                     if byte_offset=0 then
-                      classes[0]:=X86_64_SSESF_CLASS
+                      classes[0].typ:=X86_64_SSESF_CLASS
                     else
                     else
-                      { if we have e.g. a record with two successive "single"
-                        fields, we need a 64 bit rather than a 32 bit load }
-                      classes[0]:=X86_64_SSE_CLASS;
+                      begin
+                        { if we have e.g. a record with two successive "single"
+                          fields, we need a 64 bit rather than a 32 bit load }
+                        classes[0].typ:=X86_64_SSE_CLASS;
+                        classes[0].def:=getarraydef(s32floattype,2);
+                      end;
                     result:=1;
                     result:=1;
                   end;
                   end;
                 s64real:
                 s64real:
                   begin
                   begin
-                    classes[0]:=X86_64_SSEDF_CLASS;
+                    classes[0].typ:=X86_64_SSEDF_CLASS;
                     result:=1;
                     result:=1;
                   end;
                   end;
                 s80real,
                 s80real,
                 sc80real:
                 sc80real:
                   begin
                   begin
-                    classes[0]:=X86_64_X87_CLASS;
-                    classes[1]:=X86_64_X87UP_CLASS;
+                    classes[0].typ:=X86_64_X87_CLASS;
+                    classes[1].typ:=X86_64_X87UP_CLASS;
+                    classes[1].def:=def;
                     result:=2;
                     result:=2;
                   end;
                   end;
                 s64comp,
                 s64comp,
                 s64currency:
                 s64currency:
                   begin
                   begin
-                    classes[0]:=X86_64_INTEGER_CLASS;
+                    classes[0].typ:=X86_64_INTEGER_CLASS;
                     result:=1;
                     result:=1;
                   end;
                   end;
                 s128real:
                 s128real:
                   begin
                   begin
-                    classes[0]:=X86_64_SSE_CLASS;
-                    classes[1]:=X86_64_SSEUP_CLASS;
+                    classes[0].typ:=X86_64_SSE_CLASS;
+                    classes[0].def:=getarraydef(s32floattype,2);
+                    classes[1].typ:=X86_64_SSEUP_CLASS;
+                    classes[1].def:=getarraydef(s32floattype,2);
                     result:=2;
                     result:=2;
                   end;
                   end;
                 else
                 else
@@ -519,12 +639,12 @@ unit cpupara;
                 result:=0
                 result:=0
               else
               else
                 { all kinds of pointer types: class, objcclass, interface, ... }
                 { all kinds of pointer types: class, objcclass, interface, ... }
-                result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset);
+                result:=classify_as_integer_argument(def,voidpointertype.size,classes,byte_offset);
             end;
             end;
           setdef:
           setdef:
             begin
             begin
               if is_smallset(def) then
               if is_smallset(def) then
-                result:=classify_as_integer_argument(def.size,classes,byte_offset)
+                result:=classify_as_integer_argument(def,def.size,classes,byte_offset)
               else
               else
                 result:=0;
                 result:=0;
             end;
             end;
@@ -533,13 +653,13 @@ unit cpupara;
               if (tstringdef(def).stringtype in [st_shortstring,st_longstring]) then
               if (tstringdef(def).stringtype in [st_shortstring,st_longstring]) then
                 result:=0
                 result:=0
               else
               else
-                result:=classify_as_integer_argument(def.size,classes,byte_offset);
+                result:=classify_as_integer_argument(def,def.size,classes,byte_offset);
             end;
             end;
           arraydef:
           arraydef:
             begin
             begin
               { a dynamic array is treated like a pointer }
               { a dynamic array is treated like a pointer }
               if is_dynamic_array(def) then
               if is_dynamic_array(def) then
-                result:=classify_as_integer_argument(voidpointertype.size,classes,byte_offset)
+                result:=classify_as_integer_argument(def,voidpointertype.size,classes,byte_offset)
               { other special arrays are passed on the stack }
               { other special arrays are passed on the stack }
               else if is_open_array(def) or
               else if is_open_array(def) or
                       is_array_of_const(def) then
                       is_array_of_const(def) then
@@ -561,7 +681,7 @@ unit cpupara;
                 end
                 end
               else
               else
                 { pointer }
                 { pointer }
-                result:=classify_as_integer_argument(def.size,classes,byte_offset);
+                result:=classify_as_integer_argument(def,def.size,classes,byte_offset);
             end;
             end;
           variantdef:
           variantdef:
             begin
             begin
@@ -585,7 +705,10 @@ unit cpupara;
         { init the classes array, because even if classify_argument inits only
         { init the classes array, because even if classify_argument inits only
           one element we copy both to loc1/loc2 in case "1" is returned }
           one element we copy both to loc1/loc2 in case "1" is returned }
         for i:=low(classes) to high(classes) do
         for i:=low(classes) to high(classes) do
-          classes[i]:=X86_64_NO_CLASS;
+          begin
+            classes[i].typ:=X86_64_NO_CLASS;
+            classes[i].def:=nil;
+          end;
         { def.size internalerrors for open arrays and dynamic arrays, since
         { def.size internalerrors for open arrays and dynamic arrays, since
           their size cannot be determined at compile-time.
           their size cannot be determined at compile-time.
           classify_argument does not look at the realsize argument for arrays
           classify_argument does not look at the realsize argument for arrays
@@ -598,16 +721,17 @@ unit cpupara;
         case numclasses of
         case numclasses of
           0:
           0:
            begin
            begin
-             loc1:=X86_64_MEMORY_CLASS;
-             loc2:=X86_64_NO_CLASS;
+             loc1.typ:=X86_64_MEMORY_CLASS;
+             loc1.def:=def;
+             loc2.typ:=X86_64_NO_CLASS;
            end;
            end;
           1,2:
           1,2:
             begin
             begin
               { If the class is X87, X87UP or COMPLEX_X87, it is passed in memory }
               { If the class is X87, X87UP or COMPLEX_X87, it is passed in memory }
-              if classes[0] in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
-                classes[0]:=X86_64_MEMORY_CLASS;
-              if classes[1] in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
-                classes[1]:=X86_64_MEMORY_CLASS;
+              if classes[0].typ in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
+                classes[0].typ:=X86_64_MEMORY_CLASS;
+              if classes[1].typ in [X86_64_X87_CLASS,X86_64_X87UP_CLASS,X86_64_COMPLEX_X87_CLASS] then
+                classes[1].typ:=X86_64_MEMORY_CLASS;
               loc1:=classes[0];
               loc1:=classes[0];
               loc2:=classes[1];
               loc2:=classes[1];
             end
             end
@@ -625,6 +749,7 @@ unit cpupara;
       begin
       begin
         if handle_common_ret_in_param(def,pd,result) then
         if handle_common_ret_in_param(def,pd,result) then
           exit;
           exit;
+        fillchar(classes,sizeof(classes),0);
         case def.typ of
         case def.typ of
           { for records it depends on their contents and size }
           { for records it depends on their contents and size }
           recorddef,
           recorddef,
@@ -667,6 +792,7 @@ unit cpupara;
         classes: tx64paraclasses;
         classes: tx64paraclasses;
         numclasses: longint;
         numclasses: longint;
       begin
       begin
+        fillchar(classes,sizeof(classes),0);
         result:=false;
         result:=false;
         { var,out,constref always require address }
         { var,out,constref always require address }
         if varspez in [vs_var,vs_out,vs_constref] then
         if varspez in [vs_var,vs_out,vs_constref] then
@@ -766,18 +892,23 @@ unit cpupara;
     procedure tx86_64paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
     procedure tx86_64paramanager.getintparaloc(pd : tabstractprocdef; nr : longint; var cgpara : tcgpara);
       var
       var
         paraloc : pcgparalocation;
         paraloc : pcgparalocation;
-        def : tdef;
+        psym : tparavarsym;
+        pdef : tdef;
       begin
       begin
-        def:=tparavarsym(pd.paras[nr-1]).vardef;
+        psym:=tparavarsym(pd.paras[nr-1]);
+        pdef:=psym.vardef;
+        if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
+          pdef:=getpointerdef(pdef);
         cgpara.reset;
         cgpara.reset;
-        cgpara.size:=def_cgsize(def);
+        cgpara.size:=def_cgsize(pdef);
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.intsize:=tcgsize2size[cgpara.size];
         cgpara.alignment:=get_para_align(pd.proccalloption);
         cgpara.alignment:=get_para_align(pd.proccalloption);
-        cgpara.def:=def;
+        cgpara.def:=pdef;
         paraloc:=cgpara.add_location;
         paraloc:=cgpara.add_location;
         with paraloc^ do
         with paraloc^ do
          begin
          begin
-           size:=OS_INT;
+           size:=def_cgsize(pdef);
+           paraloc^.def:=pdef;
            if target_info.system=system_x86_64_win64 then
            if target_info.system=system_x86_64_win64 then
              begin
              begin
                if nr<1 then
                if nr<1 then
@@ -785,7 +916,7 @@ unit cpupara;
                else if nr<=high(paraintsupregs_winx64)+1 then
                else if nr<=high(paraintsupregs_winx64)+1 then
                  begin
                  begin
                     loc:=LOC_REGISTER;
                     loc:=LOC_REGISTER;
-                    register:=newreg(R_INTREGISTER,paraintsupregs_winx64[nr-1],R_SUBWHOLE);
+                    register:=newreg(R_INTREGISTER,paraintsupregs_winx64[nr-1],cgsize2subreg(R_INTREGISTER,size));
                  end
                  end
                else
                else
                  begin
                  begin
@@ -801,7 +932,7 @@ unit cpupara;
                else if nr<=high(paraintsupregs)+1 then
                else if nr<=high(paraintsupregs)+1 then
                  begin
                  begin
                     loc:=LOC_REGISTER;
                     loc:=LOC_REGISTER;
-                    register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],R_SUBWHOLE);
+                    register:=newreg(R_INTREGISTER,paraintsupregs[nr-1],cgsize2subreg(R_INTREGISTER,size));
                  end
                  end
                else
                else
                  begin
                  begin
@@ -847,6 +978,7 @@ unit cpupara;
         if result.def.typ=floatdef then
         if result.def.typ=floatdef then
           begin
           begin
             paraloc:=result.add_location;
             paraloc:=result.add_location;
+            paraloc^.def:=result.def;
             case tfloatdef(result.def).floattype of
             case tfloatdef(result.def).floattype of
               s32real:
               s32real:
                 begin
                 begin
@@ -878,6 +1010,7 @@ unit cpupara;
         else
         else
          { Return in register }
          { Return in register }
           begin
           begin
+            fillchar(classes,sizeof(classes),0);
             numclasses:=classify_argument(result.def,vs_value,result.def.size,classes,0);
             numclasses:=classify_argument(result.def,vs_value,result.def.size,classes,0);
             { this would mean a memory return }
             { this would mean a memory return }
             if (numclasses=0) then
             if (numclasses=0) then
@@ -890,18 +1023,30 @@ unit cpupara;
             for i:=0 to numclasses-1 do
             for i:=0 to numclasses-1 do
               begin
               begin
                 paraloc:=result.add_location;
                 paraloc:=result.add_location;
-                case classes[i] of
+                paraloc^.def:=classes[i].def;
+                case classes[i].typ of
                   X86_64_INTEGERSI_CLASS,
                   X86_64_INTEGERSI_CLASS,
                   X86_64_INTEGER_CLASS:
                   X86_64_INTEGER_CLASS:
                     begin
                     begin
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.loc:=LOC_REGISTER;
                       paraloc^.register:=intretregs[intretregidx];
                       paraloc^.register:=intretregs[intretregidx];
-                      if classes[i]=X86_64_INTEGER_CLASS then
-                        paraloc^.size:=OS_64
+                      if classes[i].typ=X86_64_INTEGER_CLASS then
+                        begin
+                          paraloc^.size:=OS_64;
+                          if paraloc^.def.size<>8 then
+                            paraloc^.def:=u64inttype;
+                        end
                       else if result.intsize in [1,2,4] then
                       else if result.intsize in [1,2,4] then
-                        paraloc^.size:=retcgsize
+                        begin
+                          paraloc^.size:=retcgsize;
+                          paraloc^.def:=result.def;
+                        end
                       else
                       else
-                        paraloc^.size:=OS_32;
+                        begin
+                          paraloc^.size:=OS_32;
+                          if paraloc^.def.size<>4 then
+                            paraloc^.def:=u32inttype;
+                        end;
                       setsubreg(paraloc^.register,cgsize2subreg(R_INTREGISTER,paraloc^.size));
                       setsubreg(paraloc^.register,cgsize2subreg(R_INTREGISTER,paraloc^.size));
                       inc(intretregidx);
                       inc(intretregidx);
                     end;
                     end;
@@ -912,7 +1057,7 @@ unit cpupara;
                     begin
                     begin
                       paraloc^.loc:=LOC_MMREGISTER;
                       paraloc^.loc:=LOC_MMREGISTER;
                       paraloc^.register:=mmretregs[mmretregidx];
                       paraloc^.register:=mmretregs[mmretregidx];
-                      case classes[i] of
+                      case classes[i].typ of
                         X86_64_SSESF_CLASS:
                         X86_64_SSESF_CLASS:
                           begin
                           begin
                             setsubreg(paraloc^.register,R_SUBMMS);
                             setsubreg(paraloc^.register,R_SUBMMS);
@@ -938,6 +1083,7 @@ unit cpupara;
                          (numclasses<>1) then
                          (numclasses<>1) then
                         internalerror(2010060302);
                         internalerror(2010060302);
                       paraloc^.loc:=LOC_VOID;
                       paraloc^.loc:=LOC_VOID;
+                      paraloc^.def:=voidtype;
                     end;
                     end;
                   else
                   else
                     internalerror(2010021504);
                     internalerror(2010021504);
@@ -974,11 +1120,12 @@ unit cpupara;
             pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
             pushaddr:=push_addr_param(hp.varspez,paradef,p.proccalloption);
             if pushaddr then
             if pushaddr then
               begin
               begin
-                loc[1]:=X86_64_INTEGER_CLASS;
-                loc[2]:=X86_64_NO_CLASS;
+                loc[1].typ:=X86_64_INTEGER_CLASS;
+                loc[2].typ:=X86_64_NO_CLASS;
                 paracgsize:=OS_ADDR;
                 paracgsize:=OS_ADDR;
                 paralen:=sizeof(pint);
                 paralen:=sizeof(pint);
                 paradef:=getpointerdef(paradef);
                 paradef:=getpointerdef(paradef);
+                loc[1].def:=paradef;
               end
               end
             else
             else
               begin
               begin
@@ -993,6 +1140,7 @@ unit cpupara;
                     paracgsize:=OS_S32;
                     paracgsize:=OS_S32;
                     paralen:=4;
                     paralen:=4;
                     paradef:=s32inttype;
                     paradef:=s32inttype;
+                    loc[1].def:=paradef;
                   end;
                   end;
               end;
               end;
 
 
@@ -1001,19 +1149,20 @@ unit cpupara;
                (target_info.system = system_x86_64_win64) and
                (target_info.system = system_x86_64_win64) and
                (paradef.typ = floatdef) then
                (paradef.typ = floatdef) then
               begin
               begin
-                loc[2]:=X86_64_NO_CLASS;
+                loc[2].typ:=X86_64_NO_CLASS;
                 if paracgsize=OS_F64 then
                 if paracgsize=OS_F64 then
                   begin
                   begin
-                    loc[1]:=X86_64_INTEGER_CLASS;
+                    loc[1].typ:=X86_64_INTEGER_CLASS;
                     paracgsize:=OS_64;
                     paracgsize:=OS_64;
                     paradef:=u64inttype;
                     paradef:=u64inttype;
                   end
                   end
                 else
                 else
                   begin
                   begin
-                    loc[1]:=X86_64_INTEGERSI_CLASS;
+                    loc[1].typ:=X86_64_INTEGERSI_CLASS;
                     paracgsize:=OS_32;
                     paracgsize:=OS_32;
                     paradef:=u32inttype;
                     paradef:=u32inttype;
                   end;
                   end;
+                loc[1].def:=paradef;
               end;
               end;
 
 
             hp.paraloc[side].reset;
             hp.paraloc[side].reset;
@@ -1027,7 +1176,7 @@ unit cpupara;
                 needintloc:=0;
                 needintloc:=0;
                 needmmloc:=0;
                 needmmloc:=0;
                 for locidx:=low(loc) to high(loc) do
                 for locidx:=low(loc) to high(loc) do
-                  case loc[locidx] of
+                  case loc[locidx].typ of
                     X86_64_INTEGER_CLASS,
                     X86_64_INTEGER_CLASS,
                     X86_64_INTEGERSI_CLASS:
                     X86_64_INTEGERSI_CLASS:
                       inc(needintloc);
                       inc(needintloc);
@@ -1048,9 +1197,10 @@ unit cpupara;
                     { If there are no registers available for any
                     { If there are no registers available for any
                       eightbyte of an argument, the whole argument is
                       eightbyte of an argument, the whole argument is
                       passed on the stack. }
                       passed on the stack. }
-                    loc[low(loc)]:=X86_64_MEMORY_CLASS;
+                    loc[low(loc)].typ:=X86_64_MEMORY_CLASS;
+                    loc[low(loc)].def:=paradef;
                     for locidx:=succ(low(loc)) to high(loc) do
                     for locidx:=succ(low(loc)) to high(loc) do
-                      loc[locidx]:=X86_64_NO_CLASS;
+                      loc[locidx].typ:=X86_64_NO_CLASS;
                   end;
                   end;
 
 
                 locidx:=1;
                 locidx:=1;
@@ -1059,31 +1209,38 @@ unit cpupara;
                     if locidx>2 then
                     if locidx>2 then
                       internalerror(200501283);
                       internalerror(200501283);
                     { Allocate }
                     { Allocate }
-                    case loc[locidx] of
+                    case loc[locidx].typ of
                       X86_64_INTEGER_CLASS,
                       X86_64_INTEGER_CLASS,
                       X86_64_INTEGERSI_CLASS:
                       X86_64_INTEGERSI_CLASS:
                         begin
                         begin
                           paraloc:=hp.paraloc[side].add_location;
                           paraloc:=hp.paraloc[side].add_location;
                           paraloc^.loc:=LOC_REGISTER;
                           paraloc^.loc:=LOC_REGISTER;
-                          if (paracgsize=OS_NO) or (loc[2]<>X86_64_NO_CLASS) then
+                          paraloc^.def:=loc[locidx].def;
+                          if (paracgsize=OS_NO) or (loc[2].typ<>X86_64_NO_CLASS) then
                             begin
                             begin
-                              if loc[locidx]=X86_64_INTEGER_CLASS then
+                              if loc[locidx].typ=X86_64_INTEGER_CLASS then
                                 begin
                                 begin
                                   paraloc^.size:=OS_INT;
                                   paraloc^.size:=OS_INT;
+                                  paraloc^.def:=u64inttype;
                                   subreg:=R_SUBWHOLE;
                                   subreg:=R_SUBWHOLE;
                                 end
                                 end
                               else
                               else
                                 begin
                                 begin
                                   paraloc^.size:=OS_32;
                                   paraloc^.size:=OS_32;
+                                  paraloc^.def:=u32inttype;
                                   subreg:=R_SUBD;
                                   subreg:=R_SUBD;
                                 end;
                                 end;
                             end
                             end
                           else
                           else
                             begin
                             begin
                               paraloc^.size:=paracgsize;
                               paraloc^.size:=paracgsize;
+                              paraloc^.def:=paradef;
                               { s64comp is pushed in an int register }
                               { s64comp is pushed in an int register }
                               if paraloc^.size=OS_C64 then
                               if paraloc^.size=OS_C64 then
-                                paraloc^.size:=OS_64;
+                                begin
+                                  paraloc^.size:=OS_64;
+                                  paraloc^.def:=u64inttype;
+                                end;
                               subreg:=cgsize2subreg(R_INTREGISTER,paraloc^.size);
                               subreg:=cgsize2subreg(R_INTREGISTER,paraloc^.size);
                             end;
                             end;
 
 
@@ -1107,8 +1264,9 @@ unit cpupara;
                         begin
                         begin
                           paraloc:=hp.paraloc[side].add_location;
                           paraloc:=hp.paraloc[side].add_location;
                           paraloc^.loc:=LOC_MMREGISTER;
                           paraloc^.loc:=LOC_MMREGISTER;
+                          paraloc^.def:=loc[locidx].def;
 
 
-                          case loc[locidx] of
+                          case loc[locidx].typ of
                             X86_64_SSESF_CLASS:
                             X86_64_SSESF_CLASS:
                               begin
                               begin
                                 subreg:=R_SUBMMS;
                                 subreg:=R_SUBMMS;
@@ -1143,6 +1301,7 @@ unit cpupara;
                         begin
                         begin
                           paraloc:=hp.paraloc[side].add_location;
                           paraloc:=hp.paraloc[side].add_location;
                           paraloc^.loc:=LOC_REFERENCE;
                           paraloc^.loc:=LOC_REFERENCE;
+                          paraloc^.def:=loc[locidx].def;
                           {Hack alert!!! We should modify int_cgsize to handle OS_128,
                           {Hack alert!!! We should modify int_cgsize to handle OS_128,
                            however, since int_cgsize is called in many places in the
                            however, since int_cgsize is called in many places in the
                            compiler where only a few can already handle OS_128, fixing it
                            compiler where only a few can already handle OS_128, fixing it
@@ -1171,7 +1330,7 @@ unit cpupara;
                         internalerror(2010053113);
                         internalerror(2010053113);
                     end;
                     end;
                     if (locidx<2) and
                     if (locidx<2) and
-                       (loc[locidx+1]<>X86_64_NO_CLASS) then
+                       (loc[locidx+1].typ<>X86_64_NO_CLASS) then
                       inc(locidx);
                       inc(locidx);
                   end;
                   end;
               end
               end
@@ -1179,6 +1338,7 @@ unit cpupara;
               begin
               begin
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc:=hp.paraloc[side].add_location;
                 paraloc^.loc:=LOC_VOID;
                 paraloc^.loc:=LOC_VOID;
+                paraloc^.def:=paradef;
               end;
               end;
           end;
           end;
         { Register parameters are assigned from left-to-right, but the
         { Register parameters are assigned from left-to-right, but the