* moved finalization of code generator temps to a node, so it can be getcopy'd

(needed for LLVM, where we need two copies of the finally code: one in case
     an exception occurs, and one in case none is raised)
   o also first finalize parameters and only then code generator temps, since
     in theory the former could create more of the latter

git-svn-id: trunk@40345 -
This commit is contained in:
Jonas Maebe 2018-11-17 22:38:36 +00:00
parent d1361ca6ed
commit 3b9f5a5e96
9 changed files with 74 additions and 32 deletions

View File

@ -4567,13 +4567,14 @@ implementation
cleanup_regvars(list); cleanup_regvars(list);
{$endif OLDREGVARS} {$endif OLDREGVARS}
{ finalize temporary data }
finalizetempvariables(list);
{ finalize paras data } { finalize paras data }
if assigned(current_procinfo.procdef.parast) and if assigned(current_procinfo.procdef.parast) and
not(po_assembler in current_procinfo.procdef.procoptions) then not(po_assembler in current_procinfo.procdef.procoptions) then
current_procinfo.procdef.parast.SymList.ForEachCall(@final_paras,list); current_procinfo.procdef.parast.SymList.ForEachCall(@final_paras,list);
{ finalize temporary data }
finalizetempvariables(list);
current_procinfo:=old_current_procinfo; current_procinfo:=old_current_procinfo;
end; end;

View File

@ -247,8 +247,6 @@ function ti386tryfinallynode.simplify(forinline: boolean): tnode;
if implicitframe then if implicitframe then
begin begin
current_procinfo.finalize_procinfo:=finalizepi; current_procinfo.finalize_procinfo:=finalizepi;
{ don't leave dangling pointer }
tcgprocinfo(current_procinfo).final_asmnode:=nil;
end; end;
end; end;
end; end;

View File

@ -59,6 +59,13 @@ interface
end; end;
tspecializenodeclass = class of tspecializenode; tspecializenodeclass = class of tspecializenode;
tfinalizetempsnode = class(tnode)
constructor create;virtual;
function pass_1 : tnode;override;
function pass_typecheck:tnode;override;
end;
tfinalizetempsnodeclass = class of tfinalizetempsnode;
tasmnode = class(tnode) tasmnode = class(tnode)
p_asm : TAsmList; p_asm : TAsmList;
currenttai : tai; currenttai : tai;
@ -289,6 +296,7 @@ interface
cnothingnode : tnothingnodeclass = tnothingnode; cnothingnode : tnothingnodeclass = tnothingnode;
cerrornode : terrornodeclass = terrornode; cerrornode : terrornodeclass = terrornode;
cspecializenode : tspecializenodeclass = tspecializenode; cspecializenode : tspecializenodeclass = tspecializenode;
cfinalizetempsnode: tfinalizetempsnodeclass = tfinalizetempsnode;
casmnode : tasmnodeclass = tasmnode; casmnode : tasmnodeclass = tasmnode;
cstatementnode : tstatementnodeclass = tstatementnode; cstatementnode : tstatementnodeclass = tstatementnode;
cblocknode : tblocknodeclass = tblocknode; cblocknode : tblocknodeclass = tblocknode;
@ -363,7 +371,6 @@ implementation
end; end;
{***************************************************************************** {*****************************************************************************
TFIRSTNOTHING TFIRSTNOTHING
*****************************************************************************} *****************************************************************************}
@ -456,6 +463,28 @@ implementation
end; end;
{*****************************************************************************
TFINALIZETEMPSNODE
*****************************************************************************}
constructor tfinalizetempsnode.create;
begin
inherited create(finalizetempsn);
end;
function tfinalizetempsnode.pass_1: tnode;
begin
result:=nil;
expectloc:=LOC_VOID;
end;
function tfinalizetempsnode.pass_typecheck: tnode;
begin
resultdef:=voidtype;
result:=nil;
end;
{***************************************************************************** {*****************************************************************************
TSTATEMENTNODE TSTATEMENTNODE
*****************************************************************************} *****************************************************************************}

View File

@ -68,6 +68,10 @@ interface
procedure pass_generate_code;override; procedure pass_generate_code;override;
end; end;
tcgfinalizetempsnode = class(tfinalizetempsnode)
procedure pass_generate_code; override;
end;
implementation implementation
uses uses
@ -714,6 +718,17 @@ interface
end; end;
{*****************************************************************************
TCGFINALIZETEMPSNODE
*****************************************************************************}
procedure tcgfinalizetempsnode.pass_generate_code;
begin
hlcg.gen_finalize_code(current_asmdata.CurrAsmList);
location.loc:=LOC_VOID;
end;
begin begin
cnothingnode:=tcgnothingnode; cnothingnode:=tcgnothingnode;
casmnode:=tcgasmnode; casmnode:=tcgasmnode;
@ -722,4 +737,5 @@ begin
ctempcreatenode:=tcgtempcreatenode; ctempcreatenode:=tcgtempcreatenode;
ctemprefnode:=tcgtemprefnode; ctemprefnode:=tcgtemprefnode;
ctempdeletenode:=tcgtempdeletenode; ctempdeletenode:=tcgtempdeletenode;
cfinalizetempsnode:=tcgfinalizetempsnode;
end. end.

View File

@ -110,7 +110,8 @@ interface
loadparentfpn, { Load the framepointer of the parent for nested procedures } loadparentfpn, { Load the framepointer of the parent for nested procedures }
objcselectorn, { node for an Objective-C message selector } objcselectorn, { node for an Objective-C message selector }
objcprotocoln, { node for an Objective-C @protocol() expression (returns metaclass associated with protocol) } objcprotocoln, { node for an Objective-C @protocol() expression (returns metaclass associated with protocol) }
specializen { parser-only node to handle Delphi-mode inline specializations } specializen, { parser-only node to handle Delphi-mode inline specializations }
finalizetempsn { Internal node used to clean up code generator temps (warning: must NOT create additional tepms that may need to be finalised!) }
); );
tnodetypeset = set of tnodetype; tnodetypeset = set of tnodetype;
@ -194,7 +195,8 @@ interface
'loadparentfpn', 'loadparentfpn',
'objcselectorn', 'objcselectorn',
'objcprotocoln', 'objcprotocoln',
'specializen'); 'specializen',
'finalizetempsn');
{ a set containing all const nodes } { a set containing all const nodes }
nodetype_const = [niln, nodetype_const = [niln,

View File

@ -963,6 +963,11 @@ implementation
end; end;
end; end;
finalizetempsn:
begin
result:=NODE_COMPLEXITY_INF;
exit;
end;
else else
begin begin
result := NODE_COMPLEXITY_INF; result := NODE_COMPLEXITY_INF;

View File

@ -156,7 +156,8 @@ implementation
'loadparentfpn', 'loadparentfpn',
'objselectorn', 'objselectorn',
'objcprotocoln', 'objcprotocoln',
'specializen' 'specializen',
'finalizetemps'
); );
var var
p: pchar; p: pchar;

View File

@ -47,9 +47,8 @@ interface
loadpara_asmnode, loadpara_asmnode,
exitlabel_asmnode, exitlabel_asmnode,
stackcheck_asmnode, stackcheck_asmnode,
init_asmnode, init_asmnode : tasmnode;
final_asmnode : tasmnode; temps_finalized : boolean;
final_used : boolean;
dfabuilder : TDFABuilder; dfabuilder : TDFABuilder;
destructor destroy;override; destructor destroy;override;
@ -678,8 +677,6 @@ implementation
destructor tcgprocinfo.destroy; destructor tcgprocinfo.destroy;
begin begin
code.free; code.free;
if not final_used then
final_asmnode.free;
inherited destroy; inherited destroy;
end; end;
@ -768,9 +765,9 @@ implementation
(cs_implicit_exceptions in current_settings.moduleswitches)) then (cs_implicit_exceptions in current_settings.moduleswitches)) then
begin begin
include(tocode.flags,nf_block_with_exit); include(tocode.flags,nf_block_with_exit);
addstatement(newstatement,final_asmnode); addstatement(newstatement,cfinalizetempsnode.create);
cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement); cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement);
final_used:=true; temps_finalized:=true;
end; end;
{ construction successful -> beforedestruction should be called { construction successful -> beforedestruction should be called
@ -880,8 +877,7 @@ implementation
{ Generate code/locations used at end of proc } { Generate code/locations used at end of proc }
current_filepos:=exitpos; current_filepos:=exitpos;
exitlabel_asmnode:=casmnode.create_get_position; exitlabel_asmnode:=casmnode.create_get_position;
final_asmnode:=casmnode.create_get_position; temps_finalized:=false;
final_used:=false;
bodyexitcode:=generate_bodyexit_block; bodyexitcode:=generate_bodyexit_block;
{ Generate procedure by combining init+body+final, { Generate procedure by combining init+body+final,
@ -914,13 +910,13 @@ implementation
current_filepos:=exitpos; current_filepos:=exitpos;
{ Generate code that will be in the try...finally } { Generate code that will be in the try...finally }
finalcode:=internalstatements(codestatement); finalcode:=internalstatements(codestatement);
addstatement(codestatement,final_asmnode); addstatement(codestatement,cfinalizetempsnode.create);
cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,codestatement); cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,codestatement);
final_used:=true; temps_finalized:=true;
current_filepos:=entrypos; current_filepos:=entrypos;
wrappedbody:=ctryfinallynode.create_implicit(code,finalcode); wrappedbody:=ctryfinallynode.create_implicit(code,finalcode);
{ afterconstruction must be called after final_asmnode, because it { afterconstruction must be called after finalizetemps, because it
has to execute after the temps have been finalised in case of a has to execute after the temps have been finalised in case of a
refcounted class (afterconstruction decreases the refcount refcounted class (afterconstruction decreases the refcount
without freeing the instance if the count becomes nil, while without freeing the instance if the count becomes nil, while
@ -947,12 +943,12 @@ implementation
addstatement(newstatement,bodyexitcode); addstatement(newstatement,bodyexitcode);
if not is_constructor then if not is_constructor then
begin begin
addstatement(newstatement,final_asmnode); addstatement(newstatement,cfinalizetempsnode.create);
cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement); cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement);
final_used:=true; temps_finalized:=true;
end; end;
end; end;
if not final_used then if not temps_finalized then
begin begin
current_filepos:=exitpos; current_filepos:=exitpos;
cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement); cnodeutils.procdef_block_add_implicit_finalize_nodes(procdef,newstatement);
@ -1569,16 +1565,13 @@ implementation
if assigned(finalize_procinfo) then if assigned(finalize_procinfo) then
generate_exceptfilter(tcgprocinfo(finalize_procinfo)) generate_exceptfilter(tcgprocinfo(finalize_procinfo))
else else if not temps_finalized then
begin begin
hlcg.gen_finalize_code(templist); hlcg.gen_finalize_code(templist);
{ the finalcode must be concated if there was no position available, { the finalcode must be concated if there was no position available,
using insertlistafter will result in an insert at the start using insertlistafter will result in an insert at the start
when currentai=nil } when currentai=nil }
if assigned(final_asmnode) and assigned(final_asmnode.currenttai) then aktproccode.concatlist(templist);
aktproccode.insertlistafter(final_asmnode.currenttai,templist)
else
aktproccode.concatlist(templist);
end; end;
{ insert exit label at the correct position } { insert exit label at the correct position }
hlcg.a_label(templist,CurrExitLabel); hlcg.a_label(templist,CurrExitLabel);
@ -1753,7 +1746,6 @@ implementation
delete_marker(exitlabel_asmnode); delete_marker(exitlabel_asmnode);
delete_marker(stackcheck_asmnode); delete_marker(stackcheck_asmnode);
delete_marker(init_asmnode); delete_marker(init_asmnode);
delete_marker(final_asmnode);
{$ifndef NoOpt} {$ifndef NoOpt}
if not(cs_no_regalloc in current_settings.globalswitches) then if not(cs_no_regalloc in current_settings.globalswitches) then

View File

@ -216,8 +216,6 @@ function tx64tryfinallynode.simplify(forinline: boolean): tnode;
if implicitframe then if implicitframe then
begin begin
current_procinfo.finalize_procinfo:=finalizepi; current_procinfo.finalize_procinfo:=finalizepi;
{ don't leave dangling pointer }
tcgprocinfo(current_procinfo).final_asmnode:=nil;
end; end;
end; end;
end; end;