diff options
author | peter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2007-08-02 20:48:53 +0000 |
---|---|---|
committer | peter <peter@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2007-08-02 20:48:53 +0000 |
commit | fca98bcf70745fdd11b8d4fee97dc9afd58e57b2 (patch) | |
tree | f14125a51e5e90900505fd489a5c2da68926289a | |
parent | 6cae84ffde39cd6e4d4dacc3e2169e195927f6bc (diff) | |
download | fpc-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.pas | 84 |
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; |