From 270fc3943295580f298f74359661950fb9beb49d Mon Sep 17 00:00:00 2001 From: sergei Date: Tue, 6 Dec 2011 19:44:24 +0000 Subject: [PATCH] * An open array/array of const parameter passed by value and requiring a local copy on heap (currently all targets except non-Darwin i386 ones) should not be placed into register and should force procedure to have an implicit finally block. * At the same time, allow non-value parameters to be placed into registers even if they have managed type (it is ok because they don't participate in implicit exception handing; explicit exception handling still forces them to memory due to logic in tabstractvarsym.is_regvar). + Added tparavarsym.needs_finalization method to handle this logic in a single place. + Added tparamanager.use_stackalloc method to determine if local copies should be allocated on heap. git-svn-id: trunk@19762 - --- compiler/paramgr.pas | 9 +++++++++ compiler/pdecsub.pas | 2 +- compiler/psub.pas | 3 +-- compiler/symsym.pas | 12 ++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler/paramgr.pas b/compiler/paramgr.pas index 0f01b74e3c..13d149b641 100644 --- a/compiler/paramgr.pas +++ b/compiler/paramgr.pas @@ -134,6 +134,8 @@ unit paramgr; { allocate room for parameters on the stack in the entry code? } function use_fixed_stack: boolean; + { whether stack pointer can be changed in the middle of procedure } + function use_stackalloc: boolean; end; @@ -467,6 +469,13 @@ implementation {$endif i386} end; + { This is a separate function because at least win64 allows stack allocations + despite of fixed stack semantics (actually supporting it requires generating + a compliant stack frame, not yet possible) } + function tparamanager.use_stackalloc: boolean; + begin + result:=not use_fixed_stack; + end; initialization ; diff --git a/compiler/pdecsub.pas b/compiler/pdecsub.pas index 299481be93..b34e3d045d 100644 --- a/compiler/pdecsub.pas +++ b/compiler/pdecsub.pas @@ -488,7 +488,7 @@ implementation exit; with tparavarsym(p) do begin - if not is_managed_type(vardef) and + if (not needs_finalization) and paramanager.push_addr_param(varspez,vardef,tprocdef(arg).proccalloption) then varregable:=vr_intreg; end; diff --git a/compiler/psub.pas b/compiler/psub.pas index 3e9b15c28c..55283fd4a8 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -144,8 +144,7 @@ implementation procedure check_finalize_paras(p:TObject;arg:pointer); begin if (tsym(p).typ=paravarsym) and - (tparavarsym(p).varspez=vs_value) and - is_managed_type(tparavarsym(p).vardef) then + tparavarsym(p).needs_finalization then include(current_procinfo.flags,pi_needs_implicit_finally); end; diff --git a/compiler/symsym.pas b/compiler/symsym.pas index a8512892a7..ef7cb21a30 100644 --- a/compiler/symsym.pas +++ b/compiler/symsym.pas @@ -206,6 +206,7 @@ interface constructor ppuload(ppufile:tcompilerppufile); destructor destroy;override; procedure ppuwrite(ppufile:tcompilerppufile);override; + function needs_finalization: boolean; end; tstaticvarsym = class(tabstractnormalvarsym) @@ -1592,6 +1593,17 @@ implementation ppufile.writeentry(ibparavarsym); end; + function tparavarsym.needs_finalization:boolean; + begin + result:=(varspez=vs_value) and + (is_managed_type(vardef) or + ( + (not (tabstractprocdef(owner.defowner).proccalloption in cdecl_pocalls)) and + (not paramanager.use_stackalloc) and + (is_open_array(vardef) or is_array_of_const(vardef)) + ) + ); + end; {**************************************************************************** TABSOLUTEVARSYM