summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpeter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2>2007-08-02 20:48:53 +0000
committerpeter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2>2007-08-02 20:48:53 +0000
commitfca98bcf70745fdd11b8d4fee97dc9afd58e57b2 (patch)
treef14125a51e5e90900505fd489a5c2da68926289a
parent6cae84ffde39cd6e4d4dacc3e2169e195927f6bc (diff)
downloadfpc-fca98bcf70745fdd11b8d4fee97dc9afd58e57b2.tar.gz
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://peter@www.freepascal.org/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: http://svn.freepascal.org/svn/fpc/branches/fixes_2_2@8215 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--compiler/x86_64/cpupara.pas84
1 files changed, 53 insertions, 31 deletions
diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas
index 4190c1a318..c36b52e603 100644
--- a/compiler/x86_64/cpupara.pas
+++ b/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;