Browse Source

* fixed passing of registers on x86-64_linux, should fix #7613

git-svn-id: trunk@4951 -
florian 19 years ago
parent
commit
5eef73c1ab
2 changed files with 52 additions and 16 deletions
  1. 33 2
      compiler/x86_64/cgcpu.pas
  2. 19 14
      compiler/x86_64/cpupara.pas

+ 33 - 2
compiler/x86_64/cgcpu.pas

@@ -26,7 +26,7 @@ unit cgcpu;
   interface
 
     uses
-       cgbase,cgobj,cgx86,
+       cgbase,cgutils,cgobj,cgx86,
        aasmbase,aasmtai,aasmdata,aasmcpu,
        cpubase,cpuinfo,cpupara,parabase,
        symdef,
@@ -37,6 +37,8 @@ unit cgcpu;
         procedure init_register_allocators;override;
         procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
         procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+
+        procedure a_param_ref(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);override;
       end;
 
 
@@ -44,7 +46,7 @@ unit cgcpu;
 
     uses
        globtype,globals,verbose,systems,cutils,
-       symsym,defutil,paramgr,fmodule,cgutils,
+       symsym,defutil,paramgr,fmodule,
        rgobj,tgobj,rgcpu;
 
 
@@ -59,6 +61,35 @@ unit cgcpu;
       end;
 
 
+    procedure tcgx86_64.a_param_ref(list : TAsmList;size : tcgsize;const r : treference;const paraloc : TCGPara);
+      var
+        tmpref, ref: treference;
+        location: pcgparalocation;
+        sizeleft: aint;
+      begin
+        location := paraloc.location;
+        tmpref := r;
+        sizeleft := paraloc.intsize;
+        while assigned(location) do
+          begin
+            case location^.loc of
+              LOC_REGISTER,LOC_CREGISTER:
+                a_load_ref_reg(list,location^.size,location^.size,tmpref,location^.register);
+              LOC_REFERENCE:
+                begin
+                  reference_reset_base(ref,location^.reference.index,location^.reference.offset);
+                  g_concatcopy(list,tmpref,ref,sizeleft);
+                end;
+              else
+                internalerror(2002081103);
+            end;
+            inc(tmpref.offset,tcgsize2size[location^.size]);
+            dec(sizeleft,tcgsize2size[location^.size]);
+            location := location^.next;
+          end;
+      end;
+
+
     procedure tcgx86_64.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
       var
         stacksize : longint;

+ 19 - 14
compiler/x86_64/cpupara.pas

@@ -96,14 +96,11 @@ unit cpupara;
              end;
            recorddef:
              begin
-               if p.size<=16 then
-                 begin
-                   if (target_info.system=system_x86_64_win64) and
-                      (p.size<=8)  then
-                     loc1:=LOC_REGISTER
-                   else
-                     loc1:=LOC_REFERENCE;
-                 end
+               { 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
                else
                  loc1:=LOC_REFERENCE;
              end;
@@ -111,8 +108,10 @@ unit cpupara;
              begin
                if is_object(p) then
                  begin
-                   if (target_info.system=system_x86_64_win64) and
-                      (p.size<=8)  then
+                   { 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
                    else
                      loc1:=LOC_REFERENCE;
@@ -122,15 +121,21 @@ unit cpupara;
              end;
            arraydef:
              begin
-               if (target_info.system=system_x86_64_win64) and
-                  not(is_special_array(p)) and
-                  (p.size<=8)  then
+               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
                else
                  loc1:=LOC_REFERENCE;
              end;
            variantdef:
-             loc1:=LOC_REFERENCE;
+             { linux abi }
+             if target_info.system<>system_x86_64_win64 then
+               loc1:=LOC_REGISTER
+             else
+               loc1:=LOC_REFERENCE;
            stringdef:
              if is_shortstring(p) or is_longstring(p) then
                loc1:=LOC_REFERENCE