diff --git a/compiler/arm/cpupara.pas b/compiler/arm/cpupara.pas index db3b04612b..7edcfb5244 100644 --- a/compiler/arm/cpupara.pas +++ b/compiler/arm/cpupara.pas @@ -159,12 +159,15 @@ unit cpupara; function tarmparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; begin + result:=false; if varspez in [vs_var,vs_out] then begin result:=true; exit; end; case def.deftype of + variantdef, + formaldef, recorddef: result:=true; arraydef: @@ -172,14 +175,14 @@ unit cpupara; is_open_array(def) or is_array_of_const(def) or is_array_constructor(def); + objectdef : + result:=is_object(def); setdef : result:=(tsetdef(def).settype<>smallset); stringdef : result:=tstringdef(def).string_typ in [st_shortstring,st_longstring]; procvardef : result:=po_methodpointer in tprocvardef(def).procoptions; - else - result:=inherited push_addr_param(varspez,def,calloption); end; end; @@ -446,7 +449,10 @@ begin end. { $Log$ - Revision 1.29 2005-01-15 21:45:35 florian + Revision 1.30 2005-02-03 20:04:49 peter + * push_addr_param must be defined per target + + Revision 1.29 2005/01/15 21:45:35 florian * arm compiler fixed Revision 1.28 2005/01/01 19:30:17 florian diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas index 8bd4c9aa87..657f260539 100644 --- a/compiler/i386/cpupara.pas +++ b/compiler/i386/cpupara.pas @@ -84,7 +84,10 @@ unit cpupara; while assigned(paraloc) do begin if (paraloc^.loc<>LOC_REFERENCE) then - result:=false; + begin + result:=false; + exit; + end; paraloc:=paraloc^.next; end; end; @@ -116,38 +119,63 @@ unit cpupara; function ti386paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; begin - case target_info.system of - system_i386_win32 : + result:=false; + { var,out always require address } + if varspez in [vs_var,vs_out] then + begin + result:=true; + exit; + end; + { Only vs_const, vs_value here } + case def.deftype of + variantdef, + formaldef : + result:=true; + recorddef : begin - case def.deftype of - recorddef : - begin - { Win32 passes small records on the stack for call by - value } - if (calloption in [pocall_stdcall,pocall_cdecl,pocall_cppdecl]) and - (varspez=vs_value) and - (def.size<=8) then - begin - result:=false; - exit; - end; - end; - arraydef : - begin - { Win32 passes arrays on the stack for call by - value } - if (calloption in [pocall_stdcall,pocall_cdecl,pocall_cppdecl]) and - (varspez=vs_value) and - (tarraydef(def).highrange>=tarraydef(def).lowrange) then - begin - result:=false; - exit; - end; - end; - end; + { Win32 passes small records on the stack for call by + value } + if (target_info.system=system_i386_win32) and + (calloption in [pocall_stdcall,pocall_cdecl,pocall_cppdecl]) and + (varspez=vs_value) and + (def.size<=8) then + result:=false + else + result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (def.size>sizeof(aint)); end; + arraydef : + begin + { Win32 passes arrays on the stack for call by + value } + if (target_info.system=system_i386_win32) and + (calloption in [pocall_stdcall,pocall_cdecl,pocall_cppdecl]) and + (varspez=vs_value) and + (tarraydef(def).highrange>=tarraydef(def).lowrange) then + result:=false + else + { array of const values are pushed on the stack } + if (calloption in [pocall_cdecl,pocall_cppdecl]) then + result:=not is_array_of_const(def) + else + begin + result:=( + (tarraydef(def).highrange>=tarraydef(def).lowrange) and + (def.size>sizeof(aint)) + ) or + is_open_array(def) or + is_array_of_const(def) or + is_array_constructor(def); + end; + end; + objectdef : + result:=is_object(def); + stringdef : + result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (tstringdef(def).string_typ in [st_shortstring,st_longstring]); + procvardef : + result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (po_methodpointer in tprocvardef(def).procoptions); + setdef : + result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (tsetdef(def).settype<>smallset); end; - result:=inherited push_addr_param(varspez,def,calloption); end; @@ -602,7 +630,10 @@ begin end. { $Log$ - Revision 1.64 2005-01-30 11:03:22 peter + Revision 1.65 2005-02-03 20:04:49 peter + * push_addr_param must be defined per target + + Revision 1.64 2005/01/30 11:03:22 peter * revert last commit Revision 1.62 2005/01/18 22:19:20 peter diff --git a/compiler/paramgr.pas b/compiler/paramgr.pas index ff2a45236d..e9b9199e35 100644 --- a/compiler/paramgr.pas +++ b/compiler/paramgr.pas @@ -52,7 +52,7 @@ unit paramgr; { Returns true if a parameter is too large to copy and only the address is pushed } - function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;virtual; + function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;virtual;abstract; { return the size of a push } function push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint; {# Returns a structure giving the information on @@ -157,53 +157,6 @@ implementation end; - { true if a parameter is too large to copy and only the address is pushed } - function tparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; - begin - result:=false; - { var,out always require address } - if varspez in [vs_var,vs_out] then - begin - result:=true; - exit; - end; - { Only vs_const, vs_value here } - case def.deftype of - variantdef, - formaldef : - result:=true; - recorddef : - result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (def.size>sizeof(aint)); - arraydef : - begin - if (calloption in [pocall_cdecl,pocall_cppdecl]) then - begin - { array of const values are pushed on the stack } - result:=not is_array_of_const(def); - end - else - begin - result:=( - (tarraydef(def).highrange>=tarraydef(def).lowrange) and - (def.size>sizeof(aint)) - ) or - is_open_array(def) or - is_array_of_const(def) or - is_array_constructor(def); - end; - end; - objectdef : - result:=is_object(def); - stringdef : - result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (tstringdef(def).string_typ in [st_shortstring,st_longstring]); - procvardef : - result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (po_methodpointer in tprocvardef(def).procoptions); - setdef : - result:=not(calloption in [pocall_cdecl,pocall_cppdecl]) and (tsetdef(def).settype<>smallset); - end; - end; - - { return the size of a push } function tparamanager.push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint; begin @@ -433,7 +386,10 @@ end. { $Log$ - Revision 1.85 2005-01-20 17:47:01 peter + Revision 1.86 2005-02-03 20:04:49 peter + * push_addr_param must be defined per target + + Revision 1.85 2005/01/20 17:47:01 peter * remove copy_value_on_stack and a_param_copy_ref Revision 1.84 2005/01/18 22:19:20 peter diff --git a/compiler/powerpc/cpupara.pas b/compiler/powerpc/cpupara.pas index 76fa96e753..695a15f00b 100644 --- a/compiler/powerpc/cpupara.pas +++ b/compiler/powerpc/cpupara.pas @@ -173,6 +173,7 @@ unit cpupara; function tppcparamanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; begin + result:=false; { var,out always require address } if varspez in [vs_var,vs_out] then begin @@ -180,6 +181,9 @@ unit cpupara; exit; end; case def.deftype of + variantdef, + formaldef : + result:=true; recorddef: result :=(target_info.abi<>abi_powerpc_aix); arraydef: @@ -187,14 +191,14 @@ unit cpupara; is_open_array(def) or is_array_of_const(def) or is_array_constructor(def); + objectdef : + result:=is_object(def); setdef : result:=(tsetdef(def).settype<>smallset); stringdef : result:=tstringdef(def).string_typ in [st_shortstring,st_longstring]; procvardef : result:=po_methodpointer in tprocvardef(def).procoptions; - else - result:=inherited push_addr_param(varspez,def,calloption); end; end; @@ -645,7 +649,10 @@ begin end. { $Log$ - Revision 1.86 2005-01-31 17:46:25 peter + Revision 1.87 2005-02-03 20:04:49 peter + * push_addr_param must be defined per target + + Revision 1.86 2005/01/31 17:46:25 peter * fixed parseparaloc Revision 1.85 2005/01/20 17:47:01 peter diff --git a/compiler/utils/samplecfg b/compiler/utils/samplecfg index c53c8cf324..520b3f19bc 100644 --- a/compiler/utils/samplecfg +++ b/compiler/utils/samplecfg @@ -162,7 +162,7 @@ cat < $thefile #-Cr #-Ct -# Optimizer switches +# Optimizer switches for i386 compiler # -Og generate smaller code # -OG generate faster code (default) # -Or keep certain variables in registers (still BUGGY!!!) diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas index 54a2e88804..8ae30cd7b4 100644 --- a/compiler/x86_64/cpupara.pas +++ b/compiler/x86_64/cpupara.pas @@ -40,6 +40,8 @@ unit cpupara; procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee;paras:tparalist; var intparareg,mmparareg,parasize:longint); public + function param_use_paraloc(const cgpara:tcgpara):boolean;override; + function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override; procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override; function get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset;override; function get_volatile_registers_mm(calloption : tproccalloption):tcpuregisterset;override; @@ -140,6 +142,66 @@ unit cpupara; end; + function tx86_64paramanager.param_use_paraloc(const cgpara:tcgpara):boolean; + var + paraloc : pcgparalocation; + begin + if not assigned(cgpara.location) then + internalerror(200410102); + result:=true; + { All locations are LOC_REFERENCE } + paraloc:=cgpara.location; + while assigned(paraloc) do + begin + if (paraloc^.loc<>LOC_REFERENCE) then + begin + result:=false; + exit; + end; + paraloc:=paraloc^.next; + end; + end; + + + { true if a parameter is too large to copy and only the address is pushed } + function tx86_64paramanager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean; + begin + result:=false; + { var,out always require address } + if varspez in [vs_var,vs_out] then + begin + result:=true; + exit; + end; + { Only vs_const, vs_value here } + case def.deftype of + variantdef, + formaldef : + result:=true; + recorddef : + result:=(def.size>sizeof(aint)); + arraydef : + begin + result:=( + (tarraydef(def).highrange>=tarraydef(def).lowrange) and + (def.size>sizeof(aint)) + ) or + is_open_array(def) or + is_array_of_const(def) or + is_array_constructor(def); + end; + objectdef : + result:=is_object(def); + stringdef : + result:=(tstringdef(def).string_typ in [st_shortstring,st_longstring]); + procvardef : + result:=(po_methodpointer in tprocvardef(def).procoptions); + setdef : + result:=(tsetdef(def).settype<>smallset); + end; + end; + + function tx86_64paramanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset; begin result:=[RS_RAX,RS_RCX,RS_RDX,RS_RSI,RS_RDI,RS_R8,RS_R9,RS_R10,RS_R11]; @@ -350,10 +412,7 @@ unit cpupara; end else begin - if (paralen<=sizeof(aint)) then - l:=paralen - else - l:=sizeof(aint); + l:=paralen; paraloc^.size:=int_cgsize(l); end; if side=callerside then @@ -433,7 +492,10 @@ begin end. { $Log$ - Revision 1.15 2005-02-03 18:32:25 peter + Revision 1.16 2005-02-03 20:04:49 peter + * push_addr_param must be defined per target + + Revision 1.15 2005/02/03 18:32:25 peter * fix extended paraloc Revision 1.14 2005/01/29 11:36:52 peter