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

git-svn-id: trunk@4951 -
This commit is contained in:
florian 2006-10-17 20:58:16 +00:00
parent 908c9741d3
commit 5eef73c1ab
2 changed files with 52 additions and 16 deletions

View File

@ -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;

View File

@ -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