Browse Source

Merged revisions 7982,7986-7987,7990-7994,7998-8000,8004-8006,8008-8012,8016,8027,8034,8036-8037,8039,8044,8046,8048,8051,8060,8071,8075-8076,8082-8083,8087-8089,8095-8096,8099-8100,8136,8187,8190,8203,8206-8207,8212-8214 via svnmerge from
svn+ssh://[email protected]/FPC/svn/fpc/trunk

........
r7982 | daniel | 2007-07-08 19:26:08 +0200 (Sun, 08 Jul 2007) | 5 lines

* Pass const params by pointer if calling convention<>register. This is
needed for the windows unit as Delphi compatibility requires const
parameters for some procedures and Delphi assumes parameters > 4 to be
passed as pointer.
........
r8214 | peter | 2007-08-02 22:46:48 +0200 (Thu, 02 Aug 2007) | 2 lines

* cleanup x86_64 structures in registers
........

git-svn-id: branches/fixes_2_2@8215 -

peter 18 years ago
parent
commit
bfdf3ed634
1 changed files with 53 additions and 31 deletions
  1. 53 31
      compiler/x86_64/cpupara.pas

+ 53 - 31
compiler/x86_64/cpupara.pas

@@ -65,7 +65,18 @@ unit cpupara;
       paraintsupregs_winx64 : array[0..3] of tsuperregister = (RS_RCX,RS_RDX,RS_R8,RS_R9);
       parammsupregs_winx64 : array[0..3] of tsuperregister = (RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3);
 
-    procedure getvalueparaloc(p : tdef;var loc1,loc2:tcgloc);
+
+    function structure_in_registers(varspez:tvarspez;size:longint):boolean;
+      begin
+        if (target_info.system=system_x86_64_win64) then
+{$warning Temporary hack: vs_const parameters are always passed by reference for win64}
+          result:=(varspez=vs_value) and (size in [1,2,4,8])
+        else
+          result:=(size<=16);
+      end;
+
+
+    procedure getvalueparaloc(varspez:tvarspez;p : tdef;var loc1,loc2:tcgloc);
       begin
         loc1:=LOC_INVALID;
         loc2:=LOC_INVALID;
@@ -96,11 +107,12 @@ unit cpupara;
              end;
            recorddef:
              begin
-               { win64 abi }
-               if ((target_info.system=system_x86_64_win64) and (p.size<=8)) or
-               { linux abi }
-                 ((target_info.system<>system_x86_64_win64) and (p.size<=16)) then
-                 loc1:=LOC_REGISTER
+               if structure_in_registers(varspez,p.size) then
+                 begin
+                   loc1:=LOC_REGISTER;
+                   if p.size>8 then
+                     loc2:=LOC_REGISTER;
+                 end
                else
                  loc1:=LOC_REFERENCE;
              end;
@@ -108,10 +120,7 @@ unit cpupara;
              begin
                if is_object(p) then
                  begin
-                   { win64 abi }
-                   if ((target_info.system=system_x86_64_win64) and (p.size<=8)) or
-                   { linux abi }
-                     ((target_info.system<>system_x86_64_win64) and (p.size<=16)) then
+                   if structure_in_registers(varspez,p.size) then
                      loc1:=LOC_REGISTER
                    else
                      loc1:=LOC_REFERENCE;
@@ -122,13 +131,12 @@ unit cpupara;
            arraydef:
              begin
                if not(is_special_array(p)) and
-                  (
-                   { win64 abi }
-                   ((target_info.system=system_x86_64_win64) and (p.size<=8)) or
-                   { linux abi }
-                   ((target_info.system<>system_x86_64_win64) and (p.size<=16))
-                  ) then
-                 loc1:=LOC_REGISTER
+                  structure_in_registers(varspez,p.size) then
+                 begin
+                   loc1:=LOC_REGISTER;
+                   if p.size>8 then
+                     loc2:=LOC_REGISTER;
+                 end
                else
                  loc1:=LOC_REFERENCE;
              end;
@@ -142,11 +150,12 @@ unit cpupara;
              if is_shortstring(p) or is_longstring(p) then
                begin
                  { handle long and shortstrings like arrays }
-                 { win64 abi }
-                 if ((target_info.system=system_x86_64_win64) and (p.size<=8)) or
-                   { linux abi }
-                   ((target_info.system<>system_x86_64_win64) and (p.size<=16)) then
-                   loc1:=LOC_REGISTER
+                 if structure_in_registers(varspez,p.size) then
+                   begin
+                     loc1:=LOC_REGISTER;
+                     if p.size>8 then
+                       loc2:=LOC_REGISTER;
+                   end
                  else
                    loc1:=LOC_REFERENCE;
                end
@@ -159,11 +168,16 @@ unit cpupara;
                loc1:=LOC_REFERENCE;
            procvardef:
              begin
-               { This is a record < 16 bytes }
                if (po_methodpointer in tprocvardef(p).procoptions) then
                  begin
-                   loc1:=LOC_REGISTER;
-                   loc2:=LOC_REGISTER;
+                   { This is a record of 16 bytes }
+                   if structure_in_registers(varspez,p.size) then
+                     begin
+                       loc1:=LOC_REGISTER;
+                       loc2:=LOC_REGISTER;
+                     end
+                   else
+                     loc1:=LOC_REFERENCE;
                  end
                else
                  loc1:=LOC_REGISTER;
@@ -224,8 +238,7 @@ unit cpupara;
           formaldef :
             result:=true;
           recorddef :
-            result:=((varspez=vs_const) and (def.size>16)) or 
-                    ((target_info.system=system_x86_64_win64) and (def.size>8));
+            result:=not structure_in_registers(varspez,def.size);
           arraydef :
             begin
               result:=not(
@@ -237,11 +250,20 @@ unit cpupara;
                          );
             end;
           objectdef :
-            result:=is_object(def);
+            begin
+              if is_object(def) then
+                result:=not structure_in_registers(varspez,def.size);
+            end;
           stringdef :
-            result:=(tstringdef(def).stringtype in [st_shortstring,st_longstring]);
+            begin
+              if (tstringdef(def).stringtype in [st_shortstring,st_longstring]) then
+                result:=not structure_in_registers(varspez,def.size);
+            end;
           procvardef :
-            result:=(po_methodpointer in tprocvardef(def).procoptions) and (target_info.system=system_x86_64_win64);
+            begin
+              if (po_methodpointer in tprocvardef(def).procoptions) then
+                result:=not structure_in_registers(varspez,def.size);
+            end;
           setdef :
             result:=(tsetdef(def).settype<>smallset);
         end;
@@ -408,7 +430,7 @@ unit cpupara;
               end
             else
               begin
-                getvalueparaloc(hp.vardef,loc[1],loc[2]);
+                getvalueparaloc(hp.varspez,hp.vardef,loc[1],loc[2]);
                 paralen:=push_size(hp.varspez,hp.vardef,p.proccalloption);
                 paracgsize:=def_cgsize(hp.vardef);
               end;